diff --git a/.aztec-sync-commit b/.aztec-sync-commit new file mode 100644 index 00000000000..851f1b74852 --- /dev/null +++ b/.aztec-sync-commit @@ -0,0 +1 @@ +5e4b46d577ebf63114a5a5a1c5b6d2947d3b2567 diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000000..0f20016d862 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,24 @@ +module.exports = { + env: { + browser: true, + es6: true, + node: true, + }, + root: true, + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint', 'prettier'], + extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], + rules: { + 'comma-spacing': ['error', { before: false, after: true }], + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': [ + 'warn', // or "error" + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], + 'prettier/prettier': 'error', + }, +}; diff --git a/.github/ACVM_NOT_PUBLISHABLE.md b/.github/ACVM_NOT_PUBLISHABLE.md new file mode 100644 index 00000000000..06c9505ebae --- /dev/null +++ b/.github/ACVM_NOT_PUBLISHABLE.md @@ -0,0 +1,12 @@ +--- +title: "ACVM crates are not publishable" +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. + +Check the [MSRV check]({{env.WORKFLOW_URL}}) workflow for details. + +This issue was raised by the workflow `{{env.WORKFLOW_NAME}}` 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 new file mode 100644 index 00000000000..5e2d4b7b77f --- /dev/null +++ b/.github/CRATES_IO_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]({{env.WORKFLOW_URL}}) workflow for details. + +This issue was raised by the workflow `{{env.WORKFLOW_NAME}}` diff --git a/.github/Cross.toml b/.github/Cross.toml new file mode 100644 index 00000000000..d8516b9ae09 --- /dev/null +++ b/.github/Cross.toml @@ -0,0 +1,8 @@ +[build.env] +passthrough = [ + "HOME", + "RUST_BACKTRACE", +] +volumes = [ + "HOME", +] diff --git a/.github/DEAD_LINKS_IN_DOCS.md b/.github/DEAD_LINKS_IN_DOCS.md new file mode 100644 index 00000000000..dcd4f44cdf2 --- /dev/null +++ b/.github/DEAD_LINKS_IN_DOCS.md @@ -0,0 +1,11 @@ +--- +title: "Docs contains dead links" +assignees: signorecello, catmcgee, critesjosh, jzaki, Savio-Sou +labels: documentation +--- + +Some of the external links in the docs are now dead. This is likely due to the thing being linked to being moved. + +Check the [Check Markdown links]({{env.WORKFLOW_URL}}) workflow for details. + +This issue was raised by the workflow `{{env.WORKFLOW_NAME}}` diff --git a/.github/JS_PUBLISH_FAILED.md b/.github/JS_PUBLISH_FAILED.md new file mode 100644 index 00000000000..f91af361d7d --- /dev/null +++ b/.github/JS_PUBLISH_FAILED.md @@ -0,0 +1,11 @@ +--- +title: "JS packages failed to publish" +assignees: TomAFrench, Savio-Sou +labels: js +--- + +The {{env.NPM_TAG}} release of the JS packages failed. + +Check the [Publish JS packages]({{env.WORKFLOW_URL}}) workflow for details. + +This issue was raised by the workflow `{{env.WORKFLOW_NAME}}` diff --git a/.github/actions/docs/build-status/action.yml b/.github/actions/docs/build-status/action.yml new file mode 100644 index 00000000000..8206dd64776 --- /dev/null +++ b/.github/actions/docs/build-status/action.yml @@ -0,0 +1,22 @@ +name: 'Get build status' +description: 'Gets the build status of a Netlify site' +inputs: + branch-name: + description: 'Branch name' + required: true + site-id: + description: Netlify site id + required: true +outputs: + deploy_status: + description: "The deploy status" + value: ${{ steps.check_deploy_status.outputs.deploy_status }} +runs: + using: "composite" + steps: + - run: ${{ github.action_path }}/script.sh + shell: bash + id: check_deploy_status + env: + BRANCH_NAME: ${{ inputs.branch-name }} + SITE_ID: ${{ inputs.site-id }} diff --git a/.github/actions/docs/build-status/script.sh b/.github/actions/docs/build-status/script.sh new file mode 100755 index 00000000000..2e86de6c173 --- /dev/null +++ b/.github/actions/docs/build-status/script.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +BRANCH_NAME=$(echo "$BRANCH_NAME" | sed -e "s#refs/[^/]*/##") +DEPLOY_STATUS=$(curl -X GET "https://api.netlify.com/api/v1/sites/$SITE_ID/deploys?branch=$BRANCH_NAME" | jq -r '.[] | select(.created_at != null) | .state' | head -1) + +echo "$SITE_ID" +MAX_RETRIES=10 +COUNT=0 +while [[ "$DEPLOY_STATUS" != "ready" && $COUNT -lt $MAX_RETRIES ]]; do + sleep 20 + DEPLOY_STATUS=$(curl -X GET "https://api.netlify.com/api/v1/sites/$SITE_ID/deploys?branch=$BRANCH_NAME" | jq -r '.[] | select(.created_at != null) | .state' | head -1) + COUNT=$((COUNT+1)) + + echo "Deploy status: $DEPLOY_STATUS" + # If deploy status is ready, set the output and exit successfully + if [[ "$DEPLOY_STATUS" == "ready" ]]; then + echo "deploy_status=success" >> $GITHUB_OUTPUT + exit 0 + elif [[ "$DEPLOY_STATUS" == "error" ]]; then + echo "deploy_status=failure" >> $GITHUB_OUTPUT + exit 1 + fi + + echo "Deploy still running. Retrying..." +done + +echo "deploy_status=failure" >> $GITHUB_OUTPUT +exit 1 diff --git a/.github/actions/install-playwright/action.yml b/.github/actions/install-playwright/action.yml new file mode 100644 index 00000000000..0bd61b38c49 --- /dev/null +++ b/.github/actions/install-playwright/action.yml @@ -0,0 +1,26 @@ +name: Install Playwright +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: 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: | + # 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/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 00000000000..d0e83dedf67 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,16 @@ +name: Install Yarn dependencies +description: Installs the workspace's yarn dependencies and caches them + +runs: + using: composite + steps: + - uses: actions/setup-node@v4 + id: node + with: + node-version: 18.19.0 + cache: 'yarn' + cache-dependency-path: 'yarn.lock' + + - name: Install + run: yarn --immutable + shell: bash diff --git a/.github/critical_libraries_status/.gitignore b/.github/critical_libraries_status/.gitignore new file mode 100644 index 00000000000..38a3cf9caf1 --- /dev/null +++ b/.github/critical_libraries_status/.gitignore @@ -0,0 +1,3 @@ +.actual.jsonl +.actual.jsonl.jq +.failures.jsonl.jq \ No newline at end of file diff --git a/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/aztec-nr.failures.jsonl b/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/aztec-nr.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-contracts.failures.jsonl b/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-contracts.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/blob.failures.jsonl b/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/blob.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/parity-lib.failures.jsonl b/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/parity-lib.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/private-kernel-lib.failures.jsonl b/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/private-kernel-lib.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib.failures.jsonl b/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/rollup-lib.failures.jsonl b/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/rollup-lib.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/types.failures.jsonl b/.github/critical_libraries_status/AztecProtocol/aztec-packages/noir-projects/noir-protocol-circuits/crates/types.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/README.md b/.github/critical_libraries_status/README.md new file mode 100644 index 00000000000..47e9d7ad6ed --- /dev/null +++ b/.github/critical_libraries_status/README.md @@ -0,0 +1,20 @@ +# Critical Libraries Status + +This directory contains one `.failures.jsonl` file per external directory that is checked by CI. +CI will run the external repository tests and compare the test failures against those recorded +in these files. If there's a difference, CI will fail. + +This allows us to mark some tests as expected to fail if we introduce breaking changes. +When tests are fixed on the external repository, CI will let us know that we need to remove +the `.failures.jsonl` failures on our side. + +The format of the `.failures.jsonl` files is one JSON per line with a failure: + +```json +{"suite":"one","name":"foo"} +``` + +If it's expected that an external repository doesn't compile (because a PR introduces breaking changes +to, say, the type system) you can remove the `.failures.jsonl` file for that repository and CI +will pass again. Once the repository compiles again, CI will let us know and require us to put +back the `.failures.jsonl` file. \ No newline at end of file diff --git a/.github/critical_libraries_status/noir-lang/ec/.failures.jsonl b/.github/critical_libraries_status/noir-lang/ec/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/eddsa/.failures.jsonl b/.github/critical_libraries_status/noir-lang/eddsa/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/mimc/.failures.jsonl b/.github/critical_libraries_status/noir-lang/mimc/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/noir-bignum/.failures.jsonl b/.github/critical_libraries_status/noir-lang/noir-bignum/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/noir-edwards/.failures.jsonl.does_not_compile b/.github/critical_libraries_status/noir-lang/noir-edwards/.failures.jsonl.does_not_compile new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/noir_base64/.failures.jsonl b/.github/critical_libraries_status/noir-lang/noir_base64/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/noir_bigcurve/.failures.jsonl.does_not_compile b/.github/critical_libraries_status/noir-lang/noir_bigcurve/.failures.jsonl.does_not_compile new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/noir_check_shuffle/.failures.jsonl b/.github/critical_libraries_status/noir-lang/noir_check_shuffle/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/noir_json_parser/.failures.jsonl b/.github/critical_libraries_status/noir-lang/noir_json_parser/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/noir_rsa/.failures.jsonl b/.github/critical_libraries_status/noir-lang/noir_rsa/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/noir_sort/.failures.jsonl b/.github/critical_libraries_status/noir-lang/noir_sort/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/noir_string_search/.failures.jsonl b/.github/critical_libraries_status/noir-lang/noir_string_search/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/schnorr/.failures.jsonl b/.github/critical_libraries_status/noir-lang/schnorr/.failures.jsonl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/critical_libraries_status/noir-lang/sparse_array/.failures.jsonl.does_not_compile b/.github/critical_libraries_status/noir-lang/sparse_array/.failures.jsonl.does_not_compile new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000000..dfb141e29f7 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,25 @@ +# Description + +## Problem\* + +Resolves + +## Summary\* + + + +## Additional Context + + + +## Documentation\* + +Check one: +- [ ] No documentation needed. +- [ ] Documentation included in this PR. +- [ ] **[For Experimental Features]** Documentation to be submitted in a separate PR. + +# PR Checklist\* + +- [ ] I have tested the changes locally. +- [ ] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. diff --git a/.github/scripts/acvm_js-build.sh b/.github/scripts/acvm_js-build.sh new file mode 100755 index 00000000000..e79967e3a8f --- /dev/null +++ b/.github/scripts/acvm_js-build.sh @@ -0,0 +1,6 @@ +#!/bin/bash +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/acvm_js-test-browser.sh b/.github/scripts/acvm_js-test-browser.sh new file mode 100755 index 00000000000..34445623988 --- /dev/null +++ b/.github/scripts/acvm_js-test-browser.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -eu + +./.github/scripts/playwright-install.sh +yarn workspace @noir-lang/acvm_js test:browser diff --git a/.github/scripts/acvm_js-test.sh b/.github/scripts/acvm_js-test.sh new file mode 100755 index 00000000000..d5519d26cc4 --- /dev/null +++ b/.github/scripts/acvm_js-test.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eu + +yarn workspace @noir-lang/acvm_js test diff --git a/.github/scripts/cargo-binstall-install.sh b/.github/scripts/cargo-binstall-install.sh new file mode 100755 index 00000000000..5cbf2cda221 --- /dev/null +++ b/.github/scripts/cargo-binstall-install.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -eu + +cd $(dirname "$0") + +CARGO_BINSTALL_CHECK=$(./command-check.sh cargo-binstall) +if [ $CARGO_BINSTALL_CHECK != "true" ]; then + curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash +fi diff --git a/.github/scripts/check_test_results.sh b/.github/scripts/check_test_results.sh new file mode 100755 index 00000000000..25833387990 --- /dev/null +++ b/.github/scripts/check_test_results.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -eu + +# Usage: ./check_test_results.sh +# Compares the output of two test results of the same repository. +# If any of the files doesn't exist or is empty, the script will consider that the test suite +# couldn't be compiled. + +function process_json_lines() { + cat $1 | jq -c 'select(.type == "test" and .event == "failed") | {suite: .suite, name: .name}' | jq -s -c 'sort_by(.suite, .name) | .[]' > $1.jq +} + +if [ -f $1 ] && [ -f $2 ]; then + # Both files exist, let's compare them + $(process_json_lines $2) + if ! diff $1 $2.jq; then + echo "Error: test failures don't match expected failures" + echo "Lines prefixed with '>' are new test failures (you could add them to '$1')" + echo "Lines prefixed with '<' are tests that were expected to fail but passed (you could remove them from '$1')" + exit -1 + fi +elif [ -f $1 ]; then + # Only the expected file exists, which means the actual test couldn't be compiled. + echo "Error: external library tests couldn't be compiled." + echo "You could rename '$1' to '$1.does_not_compile' if it's expected that the external library can't be compiled." + exit -1 +elif [ -f $2 ]; then + # Only the actual file exists, which means we are expecting the external library + # not to compile but it did. + echo "Error: expected external library not to compile, but it did." + echo "You could create '$1' with these contents:" + $(process_json_lines $2) + cat $2.jq + exit -1 +else + # Both files don't exists, which means we are expecting the external library not + # to compile, and it didn't, so all is good. + exit 0 +fi diff --git a/.github/scripts/command-check.sh b/.github/scripts/command-check.sh new file mode 100755 index 00000000000..ebe2fa52bde --- /dev/null +++ b/.github/scripts/command-check.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -eu + +command -v $1 >/dev/null 2>&1 && echo "true" || { echo >&2 "$1 is not installed" && echo "false"; } diff --git a/.github/scripts/integration-test-browser.sh b/.github/scripts/integration-test-browser.sh new file mode 100755 index 00000000000..12195a88928 --- /dev/null +++ b/.github/scripts/integration-test-browser.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -eu + +./.github/scripts/playwright-install.sh +yarn workspace integration-tests test:browser \ No newline at end of file diff --git a/.github/scripts/integration-test-node.sh b/.github/scripts/integration-test-node.sh new file mode 100755 index 00000000000..b7f00c65620 --- /dev/null +++ b/.github/scripts/integration-test-node.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -eu + +apt-get install libc++-dev -y +yarn workspace integration-tests test:node diff --git a/.github/scripts/merge-bench-reports.sh b/.github/scripts/merge-bench-reports.sh new file mode 100755 index 00000000000..23a62874148 --- /dev/null +++ b/.github/scripts/merge-bench-reports.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -eu + +echo "Merging reports" + +REPORT_NAME=$1 +NAME_PLURAL=""$REPORT_NAME"s" + +combined_reports="[]" + +# Iterate over each report and merge them +for report in ./reports/*; do + # The report is saved under ./$REPORT_NAME_{ matrix_report }/$REPORT_NAME_{ matrix_report }.json + FILE_PATH=$(echo $(ls $report)) + + # Extract the $NAME_PLURAL array from each report and merge it + combined_reports=$(jq '[."'"$NAME_PLURAL"'"[]] + '"$combined_reports" <<< "$(cat "$report/$FILE_PATH")") +done + +combined_reports=$(jq '[."'$NAME_PLURAL'"[]] + '"$combined_reports" <<< "$(cat ./$REPORT_NAME.json)") + +# Wrap the merged memory reports into a new object as to keep the $NAME_PLURAL key +final_report="{\"$NAME_PLURAL\": $combined_reports}" + +echo "$final_report" > $REPORT_NAME.json + +cat $REPORT_NAME.json \ No newline at end of file diff --git a/.github/scripts/nargo-build.sh b/.github/scripts/nargo-build.sh new file mode 100755 index 00000000000..2115732ab7e --- /dev/null +++ b/.github/scripts/nargo-build.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -eu + +export SOURCE_DATE_EPOCH=$(date +%s) +export GIT_DIRTY=false +export GIT_COMMIT=$(git rev-parse --verify HEAD) + +cargo build --release diff --git a/.github/scripts/nargo-test.sh b/.github/scripts/nargo-test.sh new file mode 100755 index 00000000000..9234df7bf5c --- /dev/null +++ b/.github/scripts/nargo-test.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -eu + +apt-get install -y curl libc++-dev + +export SOURCE_DATE_EPOCH=$(date +%s) +export GIT_DIRTY=false +export GIT_COMMIT=$(git rev-parse --verify HEAD) + +cargo test --workspace --locked --release \ No newline at end of file diff --git a/.github/scripts/noir-codegen-build.sh b/.github/scripts/noir-codegen-build.sh new file mode 100755 index 00000000000..d42be4d676e --- /dev/null +++ b/.github/scripts/noir-codegen-build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eu + +yarn workspace @noir-lang/noir_codegen build diff --git a/.github/scripts/noir-codegen-test.sh b/.github/scripts/noir-codegen-test.sh new file mode 100755 index 00000000000..6f603f65507 --- /dev/null +++ b/.github/scripts/noir-codegen-test.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eu + +yarn workspace @noir-lang/noir_codegen test \ No newline at end of file diff --git a/.github/scripts/noir-js-build.sh b/.github/scripts/noir-js-build.sh new file mode 100755 index 00000000000..04367e41342 --- /dev/null +++ b/.github/scripts/noir-js-build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eu + +yarn workspace @noir-lang/noir_js build diff --git a/.github/scripts/noir-js-test.sh b/.github/scripts/noir-js-test.sh new file mode 100755 index 00000000000..72458d8de6a --- /dev/null +++ b/.github/scripts/noir-js-test.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eu + +yarn workspace @noir-lang/noir_js test diff --git a/.github/scripts/noir-js-types-build.sh b/.github/scripts/noir-js-types-build.sh new file mode 100755 index 00000000000..77b08651d68 --- /dev/null +++ b/.github/scripts/noir-js-types-build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eu + +yarn workspace @noir-lang/types build \ No newline at end of file diff --git a/.github/scripts/noir-wasm-build.sh b/.github/scripts/noir-wasm-build.sh new file mode 100755 index 00000000000..6c0336ee0c5 --- /dev/null +++ b/.github/scripts/noir-wasm-build.sh @@ -0,0 +1,7 @@ +#!/bin/bash +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/noir-wasm-test-browser.sh b/.github/scripts/noir-wasm-test-browser.sh new file mode 100755 index 00000000000..189dee91289 --- /dev/null +++ b/.github/scripts/noir-wasm-test-browser.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -eu + +./.github/scripts/playwright-install.sh +yarn workspace @noir-lang/noir_wasm test:build_fixtures +yarn workspace @noir-lang/noir_wasm test:browser diff --git a/.github/scripts/noir-wasm-test.sh b/.github/scripts/noir-wasm-test.sh new file mode 100755 index 00000000000..a7aa6b68de2 --- /dev/null +++ b/.github/scripts/noir-wasm-test.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -eu + +yarn workspace @noir-lang/noir_wasm test:build_fixtures +yarn workspace @noir-lang/noir_wasm test:node +./.github/scripts/playwright-install.sh +yarn workspace @noir-lang/noir_wasm test:browser diff --git a/.github/scripts/noirc-abi-build.sh b/.github/scripts/noirc-abi-build.sh new file mode 100755 index 00000000000..99de474eb75 --- /dev/null +++ b/.github/scripts/noirc-abi-build.sh @@ -0,0 +1,6 @@ +#!/bin/bash +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/noirc-abi-test-browser.sh b/.github/scripts/noirc-abi-test-browser.sh new file mode 100755 index 00000000000..e03da253ebb --- /dev/null +++ b/.github/scripts/noirc-abi-test-browser.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -eu + +./.github/scripts/playwright-install.sh +yarn workspace @noir-lang/noirc_abi test:browser diff --git a/.github/scripts/noirc-abi-test.sh b/.github/scripts/noirc-abi-test.sh new file mode 100755 index 00000000000..39ca0a44b07 --- /dev/null +++ b/.github/scripts/noirc-abi-test.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eu + +yarn workspace @noir-lang/noirc_abi test diff --git a/.github/scripts/playwright-install.sh b/.github/scripts/playwright-install.sh new file mode 100755 index 00000000000..7e65021166c --- /dev/null +++ b/.github/scripts/playwright-install.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eu + +npx -y playwright@1.42 install --with-deps diff --git a/.github/scripts/wasm-bindgen-install.sh b/.github/scripts/wasm-bindgen-install.sh new file mode 100755 index 00000000000..20908003693 --- /dev/null +++ b/.github/scripts/wasm-bindgen-install.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -eu + +cd $(dirname "$0") + +./cargo-binstall-install.sh + +# Install wasm-bindgen-cli. +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 new file mode 100755 index 00000000000..218778edac6 --- /dev/null +++ b/.github/scripts/wasm-opt-install.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -eu + +cd $(dirname "$0") + +./cargo-binstall-install.sh + +cargo-binstall wasm-opt --version 0.116.0 -y --force diff --git a/.github/scripts/wasm-pack-install.sh b/.github/scripts/wasm-pack-install.sh new file mode 100755 index 00000000000..d3de47d9786 --- /dev/null +++ b/.github/scripts/wasm-pack-install.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -eu + +cd $(dirname "$0") + +./cargo-binstall-install.sh + +cargo-binstall wasm-pack --version 0.12.1 -y diff --git a/.github/workflows/cache-cleanup.yml b/.github/workflows/cache-cleanup.yml new file mode 100644 index 00000000000..bb05c5454e5 --- /dev/null +++ b/.github/workflows/cache-cleanup.yml @@ -0,0 +1,35 @@ +# This workflow cleans up any cache entries associated with a pull request once it has been closed. +# This prevents us from having many refs/pull/PR_NUMBER/merge cache entries which will never be used. +# +# Note that this will affect both PRs being closed with and without being merged. + +name: Cleanup closed PR cache entries + +on: + pull_request: + types: + - closed + +jobs: + cleanup: + runs-on: ubuntu-22.04 + steps: + - name: Cleanup + run: | + gh extension install actions/gh-actions-cache + + echo "Fetching list of cache key" + cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 ) + + ## Setting this to not fail the workflow while deleting cache keys. + set +e + echo "Deleting caches..." + for cacheKey in $cacheKeysForPR + do + gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm + done + echo "Done" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge diff --git a/.github/workflows/deny.yml b/.github/workflows/deny.yml new file mode 100644 index 00000000000..11dbc3eef4b --- /dev/null +++ b/.github/workflows/deny.yml @@ -0,0 +1,26 @@ +name: deny + +on: + push: + branches: [master] + paths: [Cargo.lock] + pull_request: + branches: [master] + paths: [Cargo.lock] + merge_group: + +env: + RUSTFLAGS: -D warnings + CARGO_TERM_COLOR: always + +concurrency: deny-${{ github.head_ref || github.run_id }} + +jobs: + deny: + name: deny + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v1 + with: + command: check all \ No newline at end of file diff --git a/.github/workflows/docs-dead-links.yml b/.github/workflows/docs-dead-links.yml new file mode 100644 index 00000000000..b46c5393f8d --- /dev/null +++ b/.github/workflows/docs-dead-links.yml @@ -0,0 +1,35 @@ +name: Check Markdown links + +on: + schedule: + # Run a check at 9 AM UTC + - cron: "0 9 * * *" + +# This will cancel previous runs when a branch or PR is updated +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} + cancel-in-progress: true + + +jobs: + markdown-link-check: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@master + - uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + use-quiet-mode: 'yes' + config-file: ./docs/link-check.config.json + folder-path: ./docs + + # Raise an issue if the previous step failed due to dead links being found + - name: Alert on dead links + uses: JasonEtco/create-an-issue@v2 + if: ${{ failure() }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WORKFLOW_NAME: ${{ github.workflow }} + WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + update_existing: true + filename: .github/DEAD_LINKS_IN_DOCS.md diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml new file mode 100644 index 00000000000..0d47176cc00 --- /dev/null +++ b/.github/workflows/docs-pr.yml @@ -0,0 +1,133 @@ +name: Deploy preview for PR + +on: + pull_request: + +jobs: + add_label: + runs-on: ubuntu-22.04 + outputs: + has_label: ${{ steps.check-labels.outputs.result }} + steps: + - name: Check if label is present + id: check-labels + uses: actions/github-script@v7.0.1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const labels = context.payload.pull_request.labels.map(label => label.name); + if (labels.includes('documentation')) { + return true; + } + + // Fetch the list of files changed in the PR + const { data: files } = await github.rest.pulls.listFiles({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + per_page: 100 + }); + + // Check if any file is within the 'docs' folder + const docsChanged = files.some(file => file.filename.startsWith('docs/')); + return docsChanged; + + - name: Add label if not present + if: steps.check-labels.outputs.result == 'true' + uses: actions/github-script@v7.0.1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const labels = context.payload.pull_request.labels.map(label => label.name); + if (!labels.includes('documentation')) { + github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: ['documentation'] + }) + } + + build_preview: + runs-on: ubuntu-22.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu + cache-on-failure: false + save-if: false + + - 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 active docs versions + run: yarn workspace docs version::stables + + - name: Build docs + env: + 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 + with: + name: docs + path: ./docs/build/ + retention-days: 3 + + + deploy_preview: + needs: [build_preview, add_label] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + if: needs.add_label.outputs.has_label == 'true' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download built docs + uses: actions/download-artifact@v4 + with: + name: docs + path: ./docs/build + + - name: Deploy to Netlify + uses: nwtgck/actions-netlify@v2.1 + with: + publish-dir: './docs/build' + github-token: ${{ secrets.GITHUB_TOKEN }} + enable-github-deployment: false + deploy-message: "Deploy from GitHub Actions for PR ${{ github.event.number }}" + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + timeout-minutes: 1 + + add_comment: + needs: [deploy_preview] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + steps: + - name: Tag dev rel in comment + uses: marocchino/sticky-pull-request-comment@v2 + with: + message: | + FYI @noir-lang/developerrelations on Noir doc changes. + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml new file mode 100644 index 00000000000..b132ba6f938 --- /dev/null +++ b/.github/workflows/formatting.yml @@ -0,0 +1,145 @@ +name: Formatting + +on: + pull_request: + merge_group: + push: + branches: + - master + +# This will cancel previous runs when a branch or PR is updated +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + clippy: + name: cargo clippy + runs-on: ubuntu-22.04 + timeout-minutes: 30 + env: + RUSTFLAGS: -Dwarnings + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + with: + targets: x86_64-unknown-linux-gnu + components: clippy, rustfmt + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Run `cargo clippy` + run: cargo clippy --all-targets --workspace --locked --release + + rustfmt: + name: cargo fmt + runs-on: ubuntu-22.04 + timeout-minutes: 30 + env: + RUSTFLAGS: -Dwarnings + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + with: + targets: x86_64-unknown-linux-gnu + components: clippy, rustfmt + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Run `cargo fmt` + run: cargo fmt --all --check + + eslint: + name: eslint + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Run `yarn lint` + run: yarn lint + + build-nargo: + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout Noir repo + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Build Nargo + run: cargo build --package nargo_cli --release + + - name: Package artifacts + run: | + mkdir dist + cp ./target/release/nargo ./dist/nargo + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: nargo + path: ./dist/* + retention-days: 3 + + nargo_fmt: + needs: [build-nargo] + name: Nargo fmt + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Format stdlib + working-directory: ./noir_stdlib + run: nargo fmt --check + + - name: Format test suite + working-directory: ./test_programs + run: ./format.sh check diff --git a/.github/workflows/publish-acvm.yml b/.github/workflows/publish-acvm.yml new file mode 100644 index 00000000000..27d927a67d1 --- /dev/null +++ b/.github/workflows/publish-acvm.yml @@ -0,0 +1,77 @@ +name: Publish ACVM crates + +on: + workflow_dispatch: + inputs: + noir-ref: + description: The acvm reference to checkout + required: true + +jobs: + publish: + name: Publish in order + runs-on: ubuntu-22.04 + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ inputs.noir-ref }} + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + # These steps are in a specific order so crate dependencies are updated first + - name: Publish acir_field + run: | + cargo publish --package acir_field + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} + + - name: Publish brillig + run: | + cargo publish --package brillig + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} + + - name: Publish acir + run: | + cargo publish --package acir + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} + + - name: Publish acvm_blackbox_solver + run: | + cargo publish --package acvm_blackbox_solver + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} + + - name: Publish bn254_blackbox_solver + run: | + cargo publish --package bn254_blackbox_solver + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} + + - name: Publish brillig_vm + run: | + cargo publish --package brillig_vm + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} + + - name: Publish acvm + run: | + cargo publish --package acvm + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.ACVM_CRATES_IO_TOKEN }} + + # Raise an issue if any package failed to publish + - name: Alert on failed publish + uses: JasonEtco/create-an-issue@v2 + if: ${{ failure() }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CRATE_VERSION: ${{ inputs.noir-ref }} + WORKFLOW_NAME: ${{ github.workflow }} + WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + update_existing: true + filename: .github/ACVM_PUBLISH_FAILED.md diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml new file mode 100644 index 00000000000..16959256d2a --- /dev/null +++ b/.github/workflows/publish-docs.yml @@ -0,0 +1,50 @@ +name: Publish documentation + +on: + push: + branches: + - master + paths: [docs/**] + workflow_dispatch: + +jobs: + publish-docs: + name: Publish docs + runs-on: ubuntu-22.04 + + steps: + - name: Checkout release branch + uses: actions/checkout@v4 + + - 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 active docs versions + run: yarn workspace docs version::stables + + - name: Build docs for deploying + run: yarn workspaces foreach -Rpt --from docs run build + + - name: Deploy to Netlify + uses: nwtgck/actions-netlify@v2.1 + with: + publish-dir: './docs/build' + production-branch: master + production-deploy: true + github-token: ${{ secrets.GITHUB_TOKEN }} + enable-github-deployment: false + deploy-message: "Deploy from GitHub Actions for tag ${{ inputs.noir-ref }}" + enable-commit-comment: false + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + timeout-minutes: 1 diff --git a/.github/workflows/publish-es-packages.yml b/.github/workflows/publish-es-packages.yml new file mode 100644 index 00000000000..76c6fce6d5e --- /dev/null +++ b/.github/workflows/publish-es-packages.yml @@ -0,0 +1,175 @@ +name: Publish Noir ES Packages + +on: + workflow_dispatch: + inputs: + noir-ref: + description: The noir reference to checkout + required: false + default: 'master' + npm-tag: + description: Repository Tag to publish under + required: false + default: 'nightly' + +run-name: Publish ES Packages from ${{ inputs.noir-ref }} under @${{ inputs.npm-tag }} tag. + +jobs: + build-noirc_abi_wasm: + runs-on: ubuntu-22.04 + steps: + - name: Checkout Noir repo + uses: actions/checkout@v4 + with: + ref: ${{ inputs.noir-ref }} + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: noirc-abi + save-if: false + + - 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 + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: noirc_abi_wasm + path: | + ./tooling/noirc_abi_wasm/nodejs + ./tooling/noirc_abi_wasm/web + retention-days: 10 + + build-noir_wasm: + runs-on: ubuntu-22.04 + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ inputs.noir-ref }} + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: noir-wasm + save-if: false + + - 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 + + - name: Build noir_wasm + run: ./.github/scripts/noir-wasm-build.sh + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: noir_wasm + path: | + ./compiler/wasm/dist + ./compiler/wasm/build + retention-days: 3 + + build-acvm_js: + runs-on: ubuntu-22.04 + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ inputs.noir-ref }} + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: acvm-js + save-if: false + + - 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 + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: acvm-js + path: | + ./acvm-repo/acvm_js/nodejs + ./acvm-repo/acvm_js/web + retention-days: 3 + + publish-es-packages: + runs-on: ubuntu-22.04 + needs: [build-acvm_js, build-noirc_abi_wasm, build-noir_wasm] + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + ref: ${{ inputs.noir-ref }} + + - uses: actions/download-artifact@v4 + with: + name: acvm-js + path: acvm-repo/acvm_js + + - uses: actions/download-artifact@v4 + with: + name: noir_wasm + path: compiler/wasm + + - uses: actions/download-artifact@v4 + with: + name: noirc_abi_wasm + path: tooling/noirc_abi_wasm + + - name: Install Yarn dependencies + run: yarn install + + - name: Build ES Packages + run: yarn build:js:only + + - name: Prepare nightly version + if: ${{ inputs.npm-tag != 'latest' }} + run: | + yarn nightly:version -- .${{ inputs.npm-tag }} + + - name: Authenticate with npm + run: "echo npmAuthToken: ${{ secrets.NPM_TOKEN }} > ~/.yarnrc.yml" + + - name: Publish ES Packages + run: yarn publish:all --access public --tag ${{ inputs.npm-tag }} + + # Raise an issue if any package failed to publish + - name: Alert on failed publish + uses: JasonEtco/create-an-issue@v2 + if: ${{ failure() }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TAG: ${{ inputs.npm-tag }} + WORKFLOW_NAME: ${{ github.workflow }} + WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + update_existing: true + filename: .github/JS_PUBLISH_FAILED.md diff --git a/.github/workflows/publish-nargo.yml b/.github/workflows/publish-nargo.yml new file mode 100644 index 00000000000..d7d9c1ea03e --- /dev/null +++ b/.github/workflows/publish-nargo.yml @@ -0,0 +1,184 @@ +name: Publish Nargo + +on: + workflow_dispatch: + # Allow pushing a manual nightly release + inputs: + tag: + description: The tag to build Nargo from (leave empty to build a nightly release from master) + required: false + features: + description: Extra feature flags to release with + required: false + publish: + description: Whether to publish the build artifacts + type: boolean + default: false + merge_group: + pull_request: + +permissions: + # Necessary to upload new release artifacts + contents: write + +jobs: + build-apple-darwin: + runs-on: macos-14 + env: + CROSS_CONFIG: ${{ github.workspace }}/.github/Cross.toml + NIGHTLY_RELEASE: ${{ inputs.tag == '' }} + strategy: + matrix: + target: [x86_64-apple-darwin, aarch64-apple-darwin] + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ inputs.tag || env.GITHUB_REF }} + + - name: Setup for Apple Silicon + if: matrix.target == 'aarch64-apple-darwin' + run: | + sudo xcode-select -s /Applications/Xcode_15.4.0.app/Contents/Developer/ + echo "SDKROOT=$(xcrun -sdk macosx$(sw_vers -productVersion) --show-sdk-path)" >> $GITHUB_ENV + echo "MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx$(sw_vers -productVersion) --show-sdk-platform-version)" >> $GITHUB_ENV + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + with: + targets: ${{ matrix.target }} + + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.target }} + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Build environment and Compile + run: | + cargo build --package nargo_cli --release --target ${{ matrix.target }} --no-default-features --features "${{ inputs.features }}" + + - name: Package artifacts + run: | + mkdir dist + cp ./target/${{ matrix.target }}/release/nargo ./dist/nargo + 7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-${{ matrix.target }}.tar.gz + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: nargo-${{ matrix.target }} + path: ./dist/* + retention-days: 3 + + - name: Upload binaries to release tag + uses: svenstaro/upload-release-action@v2 + if: ${{ inputs.publish || github.event_name == 'schedule' }} + with: + repo_name: noir-lang/noir + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ./nargo-${{ matrix.target }}.tar.gz + asset_name: nargo-${{ matrix.target }}.tar.gz + overwrite: true + tag: ${{ inputs.tag || 'nightly' }} # This will fail if `inputs.tag` is not a tag (e.g. testing a branch) + + - name: Get formatted date + id: date + if: ${{ inputs.tag == '' && inputs.publish || github.event_name == 'schedule' }} + run: echo "date=$(date '+%Y-%m-%d')" >> $GITHUB_OUTPUT + + - name: Upload binaries to release with date tag + uses: svenstaro/upload-release-action@v2 + if: ${{ inputs.tag == '' && inputs.publish || github.event_name == 'schedule' }} + with: + repo_name: noir-lang/noir + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ./nargo-${{ matrix.target }}.tar.gz + asset_name: nargo-${{ matrix.target }}.tar.gz + prerelease: true + make_latest: false + overwrite: true + tag: ${{ format('{0}-{1}', 'nightly', steps.date.outputs.date) }} + + build-linux: + runs-on: ubuntu-22.04 + env: + CROSS_CONFIG: ${{ github.workspace }}/.github/Cross.toml + NIGHTLY_RELEASE: ${{ inputs.tag == '' }} + strategy: + fail-fast: false + matrix: + target: [x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, aarch64-unknown-linux-gnu] + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ inputs.tag || env.GITHUB_REF }} + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + with: + targets: ${{ matrix.target }} + + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.target }} + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Install Cross + uses: taiki-e/install-action@v2 + with: + tool: cross@0.2.5 + + - name: Build Nargo + run: cross build --package nargo_cli --release --target=${{ matrix.target }} --no-default-features --features "${{ inputs.features }}" + + - name: Package artifacts + run: | + mkdir dist + cp ./target/${{ matrix.target }}/release/nargo ./dist/nargo + 7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-${{ matrix.target }}.tar.gz + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: nargo-${{ matrix.target }} + path: ./dist/* + retention-days: 3 + + - name: Upload binaries to release tag + uses: svenstaro/upload-release-action@v2 + if: ${{ inputs.publish }} + with: + repo_name: noir-lang/noir + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ./nargo-${{ matrix.target }}.tar.gz + asset_name: nargo-${{ matrix.target }}.tar.gz + prerelease: true + overwrite: true + tag: ${{ inputs.tag || 'nightly' }} # This will fail if `inputs.tag` is not a tag (e.g. testing a branch) + + - name: Get formatted date + id: date + if: ${{ env.NIGHTLY_RELEASE && inputs.publish }} + run: echo "date=$(date '+%Y-%m-%d')" >> $GITHUB_OUTPUT + + - name: Upload binaries to release with date tag + uses: svenstaro/upload-release-action@v2 + if: ${{ env.NIGHTLY_RELEASE && inputs.publish }} + with: + repo_name: noir-lang/noir + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ./nargo-${{ matrix.target }}.tar.gz + asset_name: nargo-${{ matrix.target }}.tar.gz + prerelease: true + make_latest: false + overwrite: true + tag: ${{ format('{0}-{1}', 'nightly', steps.date.outputs.date) }} + + diff --git a/.github/workflows/publish-nightly.yml b/.github/workflows/publish-nightly.yml new file mode 100644 index 00000000000..2eef9ab60f7 --- /dev/null +++ b/.github/workflows/publish-nightly.yml @@ -0,0 +1,26 @@ +name: Publish Nightly release +on: + workflow_dispatch: + schedule: + # Run a nightly release at 2 AM UTC + - cron: "0 2 * * *" + +jobs: + dispatch-publish-es: + runs-on: ubuntu-22.04 + steps: + - name: Dispatch to publish-nargo + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: publish-nargo.yml + token: ${{ secrets.NOIR_REPO_TOKEN }} + # Omitting a tag results in a nightly + inputs: "{ \"publish\": true }" + + + - name: Dispatch to publish-es-packages + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: publish-es-packages.yml + token: ${{ secrets.NOIR_REPO_TOKEN }} + inputs: "{ \"noir-ref\": \"${{ env.GITHUB_REF }}\", \"npm-tag\": \"nightly\" }" diff --git a/.github/workflows/pull-request-title.yml b/.github/workflows/pull-request-title.yml new file mode 100644 index 00000000000..41922bd32ab --- /dev/null +++ b/.github/workflows/pull-request-title.yml @@ -0,0 +1,48 @@ +name: Pull Request + +on: + merge_group: + pull_request_target: + types: + - opened + - reopened + - edited + - synchronize + +permissions: + pull-requests: read + +jobs: + conventional-title: + name: Validate PR title is Conventional Commit + runs-on: ubuntu-22.04 + steps: + - name: Check title + if: github.event_name == 'pull_request_target' + uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + fix + feat + chore + + force-push-comment: + name: Warn external contributors about force-pushing + runs-on: ubuntu-22.04 + if: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != 'noir-lang/noir' }} + permissions: + pull-requests: write + + steps: + - name: Post comment on force pushes + uses: marocchino/sticky-pull-request-comment@v2 + with: + message: | + Thank you for your contribution to the Noir language. + + Please **do not force push to this branch** after the Noir team have started review of this PR. Doing so will only delay us merging your PR as we will need to start the review process from scratch. + + Thanks for your understanding. + \ No newline at end of file diff --git a/.github/workflows/recrawler.yml b/.github/workflows/recrawler.yml new file mode 100644 index 00000000000..808e5819353 --- /dev/null +++ b/.github/workflows/recrawler.yml @@ -0,0 +1,22 @@ +name: Algolia Recrawl +on: + push: + branches: [ master ] + workflow_dispatch: + +jobs: + algolia_recrawl: + name: Algolia Recrawl + runs-on: ubuntu-22.04 + steps: + - name: Algolia crawler creation and crawl + uses: algolia/algoliasearch-crawler-github-actions@v1.1.0 + id: algolia_crawler + with: + crawler-user-id: ${{ secrets.CRAWLER_USER_ID }} + crawler-api-key: ${{ secrets.CRAWLER_API_KEY }} + algolia-app-id: ${{ secrets.ALGOLIA_APP_ID }} + algolia-api-key: ${{ secrets.ALGOLIA_API_KEY }} + site-url: 'https://noir-lang.org/' + crawler-name: noir-lang + override-config: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000..bbe9a7fff62 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,186 @@ +name: Release + +on: + push: + branches: + - master + +jobs: + release-please: + name: Create Release + outputs: + release-pr: ${{ steps.release.outputs.pr }} + tag-name: ${{ steps.release.outputs.tag_name }} + runs-on: ubuntu-22.04 + steps: + - name: Run release-please + id: release + uses: googleapis/release-please-action@v4 + with: + token: ${{ secrets.NOIR_RELEASES_TOKEN }} + + update-acvm-workspace-package-versions: + name: Update acvm workspace package versions + needs: [release-please] + if: ${{ needs.release-please.outputs.release-pr }} + runs-on: ubuntu-22.04 + steps: + - name: Checkout release branch + uses: actions/checkout@v4 + with: + ref: ${{ fromJSON(needs.release-please.outputs.release-pr).headBranchName }} + token: ${{ secrets.NOIR_RELEASES_TOKEN }} + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.65.0 + + - name: Update ACVM workspace root versions + run: | + ./scripts/update-acvm-workspace-versions.sh + + - name: Update lockfile + run: | + cargo update --workspace + + - uses: actions/setup-node@v3 + with: + node-version: 18.19.0 + cache: 'yarn' + cache-dependency-path: 'yarn.lock' + + - name: Update yarn.lock + run: yarn + + - name: Configure git + run: | + git config user.name noirwhal + git config user.email tomfrench@aztecprotocol.com + + - name: Commit updates + run: | + git add . + git commit -m 'chore: Update root workspace acvm versions and lockfile' + git push + + update-docs: + name: Update docs + needs: [release-please, update-acvm-workspace-package-versions] + if: ${{ needs.release-please.outputs.release-pr }} + runs-on: ubuntu-22.04 + + steps: + - name: Checkout release branch + uses: actions/checkout@v4 + with: + ref: ${{ fromJSON(needs.release-please.outputs.release-pr).headBranchName }} + token: ${{ secrets.NOIR_RELEASES_TOKEN }} + + - name: 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: | + NOIR_VERSION=$(grep '^version =' ./Cargo.toml | sed -E 's/version = "([^"]+)"/v\1/') + echo "semver=$NOIR_VERSION" >> $GITHUB_OUTPUT + + - name: Cut a new version + working-directory: ./docs + run: yarn version ${{ steps.noir-version.outputs.semver }} + + - name: Configure git + run: | + git config --local user.name noirwhal + git config --local user.email tomfrench@aztecprotocol.com + + - name: Commit new documentation version + run: | + git add . + 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-22.04 + # We want this job to always run (even if the dependant jobs fail) as we need apply changes to the sticky comment. + if: ${{ always() }} + + 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] + if: ${{ needs.release-please.outputs.tag-name }} + runs-on: ubuntu-22.04 + steps: + - name: Dispatch to publish workflow + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: publish-nargo.yml + repo: noir-lang/noir + ref: master + token: ${{ secrets.GITHUB_TOKEN }} + inputs: '{ "tag": "${{ needs.release-please.outputs.tag-name }}", "publish": true }' + + publish-es-packages: + name: Publish ES packages + needs: [release-please] + if: ${{ needs.release-please.outputs.tag-name }} + runs-on: ubuntu-22.04 + steps: + - name: Dispatch to publish-es-packages + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: publish-es-packages.yml + ref: master + token: ${{ secrets.NOIR_REPO_TOKEN }} + inputs: '{ "noir-ref": "${{ needs.release-please.outputs.tag-name }}", "npm-tag": "latest" }' + + publish-acvm: + name: Publish acvm + needs: [release-please] + if: ${{ needs.release-please.outputs.tag-name }} + runs-on: ubuntu-22.04 + + steps: + - name: Dispatch to publish-acvm + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: publish-acvm.yml + ref: master + token: ${{ secrets.NOIR_REPO_TOKEN }} + inputs: '{ "noir-ref": "${{ needs.release-please.outputs.tag-name }}" }' diff --git a/.github/workflows/reports.yml b/.github/workflows/reports.yml new file mode 100644 index 00000000000..2ebae3f5fc4 --- /dev/null +++ b/.github/workflows/reports.yml @@ -0,0 +1,752 @@ +name: Reports + +on: + push: + branches: + - master + pull_request: + +jobs: + build-nargo: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout Noir repo + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Build Nargo + run: cargo build --package nargo_cli --release + + - name: Package artifacts + run: | + mkdir dist + cp ./target/release/nargo ./dist/nargo + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: nargo + path: ./dist/* + retention-days: 3 + + compare_gates_reports: + name: Circuit sizes + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Install `bb` + run: | + ./scripts/install_bb.sh + echo "$HOME/.bb/" >> $GITHUB_PATH + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate gates report + working-directory: ./test_programs + run: | + ./rebuild.sh + ./gates_report.sh + mv gates_report.json ../gates_report.json + + - name: Compare gates reports + id: gates_diff + uses: noir-lang/noir-gates-diff@7e4ddaa91c69380f15ccba514eac17bc7432a8cc + with: + report: gates_report.json + summaryQuantile: 0.9 # only display the 10% most significant circuit size diffs in the summary (defaults to 20%) + + - name: Add gates diff to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + # delete the comment in case changes no longer impact circuit sizes + delete: ${{ !steps.gates_diff.outputs.markdown }} + message: ${{ steps.gates_diff.outputs.markdown }} + + compare_brillig_bytecode_size_reports: + name: Brillig bytecode sizes + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate Brillig bytecode size report + working-directory: ./test_programs + run: | + mkdir ./reports + + ./gates_report_brillig.sh 9223372036854775807 + jq '.programs |= map(.package_name |= (. + "_inliner_max"))' gates_report_brillig.json > ./reports/gates_report_brillig_inliner_max.json + + ./gates_report_brillig.sh 0 + jq '.programs |= map(.package_name |= (. + "_inliner_zero"))' gates_report_brillig.json > ./reports/gates_report_brillig_inliner_zero.json + + ./gates_report_brillig.sh -9223372036854775808 + jq '.programs |= map(.package_name |= (. + "_inliner_min"))' gates_report_brillig.json > ./reports/gates_report_brillig_inliner_min.json + + # Merge all reports + jq -s '{ programs: map(.programs) | add }' ./reports/* > ../gates_report_brillig.json + + - name: Compare Brillig bytecode size reports + id: brillig_bytecode_diff + uses: noir-lang/noir-gates-diff@7e4ddaa91c69380f15ccba514eac17bc7432a8cc + with: + report: gates_report_brillig.json + header: | + # Changes to Brillig bytecode sizes + brillig_report: true + summaryQuantile: 0.9 # only display the 10% most significant bytecode size diffs in the summary (defaults to 20%) + + - name: Add bytecode size diff to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: brillig + # delete the comment in case changes no longer impact brillig bytecode sizes + delete: ${{ !steps.brillig_bytecode_diff.outputs.markdown }} + message: ${{ steps.brillig_bytecode_diff.outputs.markdown }} + + compare_brillig_execution_reports: + name: Brillig execution trace sizes + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate Brillig execution report + working-directory: ./test_programs + run: | + mkdir ./reports + + ./gates_report_brillig_execution.sh 9223372036854775807 + jq '.programs |= map(.package_name |= (. + "_inliner_max"))' gates_report_brillig_execution.json > ./reports/gates_report_brillig_execution_inliner_max.json + + ./gates_report_brillig_execution.sh 0 + jq '.programs |= map(.package_name |= (. + "_inliner_zero"))' gates_report_brillig_execution.json > ./reports/gates_report_brillig_execution_inliner_zero.json + + ./gates_report_brillig_execution.sh -9223372036854775808 + jq '.programs |= map(.package_name |= (. + "_inliner_min"))' gates_report_brillig_execution.json > ./reports/gates_report_brillig_execution_inliner_min.json + + # Merge all reports + jq -s '{ programs: map(.programs) | add }' ./reports/* > ../gates_report_brillig_execution.json + + - name: Compare Brillig execution reports + id: brillig_execution_diff + uses: noir-lang/noir-gates-diff@c1503343c3e264925ef67c68a2a5eeadd245a77b + with: + report: gates_report_brillig_execution.json + header: | + # Changes to number of Brillig opcodes executed + brillig_report: true + summaryQuantile: 0.9 # only display the 10% most significant bytecode size diffs in the summary (defaults to 20%) + + - name: Add bytecode size diff to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: brillig_execution + # delete the comment in case changes no longer impact brillig bytecode sizes + delete: ${{ !steps.brillig_execution_diff.outputs.markdown }} + message: ${{ steps.brillig_execution_diff.outputs.markdown }} + + generate_memory_report: + name: Peak memory usage + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate Memory report + working-directory: ./test_programs + run: | + ./memory_report.sh + mv memory_report.json ../memory_report.json + + - name: Upload compilation memory report + uses: actions/upload-artifact@v4 + with: + name: in_progress_compilation_mem_report + path: memory_report.json + retention-days: 3 + overwrite: true + + - name: Generate execution memory report + working-directory: ./test_programs + run: | + ./memory_report.sh 0 1 + mv memory_report.json ../memory_report.json + + - name: Upload execution memory report + uses: actions/upload-artifact@v4 + with: + name: in_progress_execution_mem_report + path: memory_report.json + retention-days: 3 + overwrite: true + + generate_compilation_and_execution_report: + name: Compilation and execution time + needs: [build-nargo] + runs-on: ubuntu-22.04 + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Generate Compilation report + working-directory: ./test_programs + run: | + ./compilation_report.sh 0 1 + mv compilation_report.json ../compilation_report.json + + - name: Generate Execution report + working-directory: ./test_programs + run: | + ./execution_report.sh 0 1 + mv execution_report.json ../execution_report.json + + - name: Upload compilation report + uses: actions/upload-artifact@v4 + with: + name: in_progress_compilation_report + path: compilation_report.json + retention-days: 3 + overwrite: true + + - name: Upload execution report + uses: actions/upload-artifact@v4 + with: + name: in_progress_execution_report + path: execution_report.json + retention-days: 3 + overwrite: true + + external_repo_compilation_and_execution_report: + needs: [build-nargo] + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + include: + # - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-contracts, cannot_execute: true } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-inner, num_runs: 5 } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-tail, num_runs: 5 } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-reset, num_runs: 5 } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-private, num_runs: 5 } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-public, num_runs: 5 } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-merge, num_runs: 5 } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-root-empty, num_runs: 5, cannot_execute: true } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-root-single-tx, num_runs: 1, flags: "--skip-brillig-constraints-check --skip-underconstrained-check", cannot_execute: true } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-root, num_runs: 1, flags: "--skip-brillig-constraints-check --skip-underconstrained-check" } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-merge, num_runs: 5 } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-root, num_runs: 5 } + + name: External repo compilation and execution reports - ${{ matrix.project.repo }}/${{ matrix.project.path }} + steps: + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - uses: actions/checkout@v4 + with: + path: scripts + sparse-checkout: | + test_programs/compilation_report.sh + test_programs/execution_report.sh + test_programs/parse_time.sh + sparse-checkout-cone-mode: false + + - name: Checkout + uses: actions/checkout@v4 + with: + repository: ${{ matrix.project.repo }} + path: test-repo + ref: ${{ matrix.project.ref }} + + - name: Generate compilation report + working-directory: ./test-repo/${{ matrix.project.path }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/compilation_report.sh ./compilation_report.sh + touch parse_time.sh + chmod +x parse_time.sh + cp /home/runner/work/noir/noir/scripts/test_programs/parse_time.sh ./parse_time.sh + ./compilation_report.sh 1 ${{ matrix.project.num_runs }} + env: + FLAGS: ${{ matrix.project.flags }} + + - name: Generate execution report + working-directory: ./test-repo/${{ matrix.project.path }} + if: ${{ !matrix.project.cannot_execute }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/execution_report.sh ./execution_report.sh + mv /home/runner/work/noir/noir/scripts/test_programs/parse_time.sh ./parse_time.sh + ./execution_report.sh 1 ${{ matrix.project.num_runs }} + + - name: Move compilation report + id: compilation_report + shell: bash + run: | + PACKAGE_NAME=${{ matrix.project.path }} + PACKAGE_NAME=$(basename $PACKAGE_NAME) + mv ./test-repo/${{ matrix.project.path }}/compilation_report.json ./compilation_report_$PACKAGE_NAME.json + echo "compilation_report_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT + + - name: Move execution report + id: execution_report + shell: bash + if: ${{ !matrix.project.cannot_execute }} + run: | + PACKAGE_NAME=${{ matrix.project.path }} + PACKAGE_NAME=$(basename $PACKAGE_NAME) + mv ./test-repo/${{ matrix.project.path }}/execution_report.json ./execution_report_$PACKAGE_NAME.json + echo "execution_report_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT + + - name: Upload compilation report + uses: actions/upload-artifact@v4 + with: + name: compilation_report_${{ steps.compilation_report.outputs.compilation_report_name }} + path: compilation_report_${{ steps.compilation_report.outputs.compilation_report_name }}.json + retention-days: 3 + overwrite: true + + - name: Upload execution report + uses: actions/upload-artifact@v4 + with: + name: execution_report_${{ steps.execution_report.outputs.execution_report_name }} + path: execution_report_${{ steps.execution_report.outputs.execution_report_name }}.json + retention-days: 3 + overwrite: true + + upload_compilation_report: + name: Upload compilation report + needs: [generate_compilation_and_execution_report, external_repo_compilation_and_execution_report] + # We want this job to run even if one variation of the matrix in `external_repo_compilation_and_execution_report` fails + if: always() + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download initial compilation report + uses: actions/download-artifact@v4 + with: + name: in_progress_compilation_report + + - name: Download matrix compilation reports + uses: actions/download-artifact@v4 + with: + pattern: compilation_report_* + path: ./reports + + - name: Merge compilation reports using jq + run: | + mv ./.github/scripts/merge-bench-reports.sh merge-bench-reports.sh + ./merge-bench-reports.sh compilation_report + + - name: Parse compilation report + id: compilation_report + uses: noir-lang/noir-bench-report@6ba151d7795042c4ff51864fbeb13c0a6a79246c + with: + report: compilation_report.json + header: | + Compilation Report + memory_report: false + + - name: Add memory report to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: compilation + message: ${{ steps.compilation_report.outputs.markdown }} + + external_repo_memory_report: + needs: [build-nargo] + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + # TODO: Bring this report back under a flag. The `noir-contracts` report takes just under 30 minutes. + # - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-contracts } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-inner } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-tail } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-reset } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-private } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-public } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-merge } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-root-empty, cannot_execute: true } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-root-single-tx, flags: "--skip-brillig-constraints-check --skip-underconstrained-check", cannot_execute: true } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-block-root, flags: "--skip-brillig-constraints-check --skip-underconstrained-check" } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-merge } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-root } + + name: External repo memory report - ${{ matrix.project.repo }}/${{ matrix.project.path }} + steps: + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - uses: actions/checkout@v4 + with: + path: scripts + sparse-checkout: | + test_programs/memory_report.sh + sparse-checkout-cone-mode: false + + - name: Checkout + uses: actions/checkout@v4 + with: + repository: ${{ matrix.project.repo }} + path: test-repo + ref: ${{ matrix.project.ref }} + + - name: Generate compilation memory report + working-directory: ./test-repo/${{ matrix.project.path }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/memory_report.sh ./memory_report.sh + ./memory_report.sh 1 + # Rename the memory report as the execution report is about to write to the same file + cp memory_report.json compilation_memory_report.json + env: + FLAGS: ${{ matrix.project.flags }} + + - name: Generate execution memory report + working-directory: ./test-repo/${{ matrix.project.path }} + if: ${{ !matrix.project.cannot_execute }} + run: | + ./memory_report.sh 1 1 + + - name: Move compilation report + id: compilation_mem_report + shell: bash + run: | + PACKAGE_NAME=${{ matrix.project.path }} + PACKAGE_NAME=$(basename $PACKAGE_NAME) + mv ./test-repo/${{ matrix.project.path }}/compilation_memory_report.json ./memory_report_$PACKAGE_NAME.json + echo "memory_report_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT + + - name: Upload compilation memory report + uses: actions/upload-artifact@v4 + with: + name: compilation_mem_report_${{ steps.compilation_mem_report.outputs.memory_report_name }} + path: memory_report_${{ steps.compilation_mem_report.outputs.memory_report_name }}.json + retention-days: 3 + overwrite: true + + - name: Move execution report + id: execution_mem_report + if: ${{ !matrix.project.cannot_execute }} + shell: bash + run: | + PACKAGE_NAME=${{ matrix.project.path }} + PACKAGE_NAME=$(basename $PACKAGE_NAME) + mv ./test-repo/${{ matrix.project.path }}/memory_report.json ./memory_report_$PACKAGE_NAME.json + echo "memory_report_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT + + - name: Upload execution memory report + uses: actions/upload-artifact@v4 + with: + name: execution_mem_report_${{ steps.execution_mem_report.outputs.memory_report_name }} + path: memory_report_${{ steps.execution_mem_report.outputs.memory_report_name }}.json + retention-days: 3 + overwrite: true + + upload_compilation_memory_report: + name: Upload compilation memory report + needs: [generate_memory_report, external_repo_memory_report] + # We want this job to run even if one variation of the matrix in `external_repo_memory_report` fails + if: always() + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download initial memory report + uses: actions/download-artifact@v4 + with: + name: in_progress_compilation_mem_report + + - name: Download matrix memory reports + uses: actions/download-artifact@v4 + with: + pattern: compilation_mem_report_* + path: ./reports + + - name: Merge memory reports using jq + run: | + mv ./.github/scripts/merge-bench-reports.sh merge-bench-reports.sh + ./merge-bench-reports.sh memory_report + + - name: Parse compilation memory report + id: compilation_mem_report + uses: noir-lang/noir-bench-report@6ba151d7795042c4ff51864fbeb13c0a6a79246c + with: + report: memory_report.json + header: | + Compilation Memory Report + memory_report: true + + - name: Add memory report to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: compilation_memory + message: ${{ steps.compilation_mem_report.outputs.markdown }} + + upload_execution_memory_report: + name: Upload execution memory report + needs: [generate_memory_report, external_repo_memory_report] + # We want this job to run even if one variation of the matrix in `external_repo_memory_report` fails + if: always() + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download initial memory report + uses: actions/download-artifact@v4 + with: + name: in_progress_execution_mem_report + + - name: Download matrix memory reports + uses: actions/download-artifact@v4 + with: + pattern: execution_mem_report_* + path: ./reports + + - name: Merge memory reports using jq + run: | + mv ./.github/scripts/merge-bench-reports.sh merge-bench-reports.sh + ./merge-bench-reports.sh memory_report + # Rename the memory report as to not clash with the compilation memory report file name + cp memory_report.json execution_memory_report.json + + - name: Parse execution memory report + id: execution_mem_report + uses: noir-lang/noir-bench-report@6ba151d7795042c4ff51864fbeb13c0a6a79246c + with: + report: execution_memory_report.json + header: | + Execution Memory Report + memory_report: true + + - name: Add execution memory report to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: execution_memory + message: ${{ steps.execution_mem_report.outputs.markdown }} + + upload_execution_report: + name: Upload execution report + needs: [generate_compilation_and_execution_report, external_repo_compilation_and_execution_report] + # We want this job to run even if one variation of the matrix in `external_repo_compilation_and_execution_report` fails + if: always() + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download initial execution report + uses: actions/download-artifact@v4 + with: + name: in_progress_execution_report + + - name: Download matrix execution reports + uses: actions/download-artifact@v4 + with: + pattern: execution_report_* + path: ./reports + + - name: Merge execution reports using jq + run: | + mv ./.github/scripts/merge-bench-reports.sh merge-bench-reports.sh + ./merge-bench-reports.sh execution_report + + - name: Parse execution report + id: execution_report + uses: noir-lang/noir-bench-report@6ba151d7795042c4ff51864fbeb13c0a6a79246c + with: + report: execution_report.json + header: | + Execution Report + execution_report: true + + - name: Add memory report to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: execution_time + message: ${{ steps.execution_report.outputs.markdown }} + + upload_benchmarks: + name: Upload benchmarks + needs: [generate_memory_report, external_repo_memory_report] + # We always push new benchmarks so we want this to only run on master to avoid garbage data.`` + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + permissions: + # deployments permission to deploy GitHub pages website + deployments: write + # contents permission to update benchmark contents in gh-pages branch + contents: write + + steps: + - uses: actions/checkout@v4 + + - name: Download initial memory report + uses: actions/download-artifact@v4 + with: + name: in_progress_compilation_mem_report + + - name: Download matrix memory reports + uses: actions/download-artifact@v4 + with: + pattern: compilation_mem_report_* + path: ./reports + + - name: Merge memory reports using jq + run: | + mv ./.github/scripts/merge-bench-reports.sh merge-bench-reports.sh + ./merge-bench-reports.sh memory_report + + - name: Convert to `benchmark-action` format + run: | + jq ".memory_reports | map({name: .artifact_name, value: (.peak_memory | tonumber), unit: \"MB\"}) " ./memory_report.json > memory_bench.json + + - name: Store benchmark result + continue-on-error: true + uses: benchmark-action/github-action-benchmark@4de1bed97a47495fc4c5404952da0499e31f5c29 + with: + name: "Compilation Memory" + tool: "customSmallerIsBetter" + output-file-path: ./memory_bench.json + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: true + alert-threshold: "110%" + comment-on-alert: true + fail-on-alert: false + alert-comment-cc-users: "@TomAFrench" + max-items-in-chart: 50 diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml new file mode 100644 index 00000000000..2b9a1461231 --- /dev/null +++ b/.github/workflows/spellcheck.yml @@ -0,0 +1,39 @@ +name: Spellcheck + +on: [pull_request] + +# This will cancel previous runs when a branch or PR is updated +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + code: + name: Code + runs-on: ubuntu-22.04 + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Check spelling + uses: streetsidesoftware/cspell-action@v2 + with: + strict: false # Do not fail, if a spelling mistake is found (This can be annoying for contributors) + incremental_files_only: true # Run this action on files which have changed in PR + files: | + **/*.{md,rs} + + docs: + name: Documentation + runs-on: ubuntu-22.04 + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Check spelling + uses: streetsidesoftware/cspell-action@v2 + with: + strict: true # Documentation has higher standards for correctness. + incremental_files_only: true # Run this action on files which have changed in PR + files: | + ./docs/**/*.md diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml new file mode 100644 index 00000000000..3fabf8ce39a --- /dev/null +++ b/.github/workflows/test-js-packages.yml @@ -0,0 +1,642 @@ +name: Javascript Tests + +on: + pull_request: + merge_group: + push: + branches: + - master + +# This will cancel previous runs when a branch or PR is updated +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + yarn-lock: + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Errors if installation would result in modifications to yarn.lock + - name: Install + run: yarn --immutable + shell: bash + + build-nargo: + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout Noir repo + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Build Nargo + run: cargo build --package nargo_cli --release + + - name: Package artifacts + run: | + mkdir dist + cp ./target/release/nargo ./dist/nargo + 7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-x86_64-unknown-linux-gnu.tar.gz + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: nargo + path: ./dist/* + retention-days: 3 + + build-noirc-abi: + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout Noir repo + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: noirc-abi + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Build noirc_abi + run: ./.github/scripts/noirc-abi-build.sh + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: noirc_abi_wasm + path: | + ./tooling/noirc_abi_wasm/nodejs + ./tooling/noirc_abi_wasm/web + retention-days: 10 + + build-noir-wasm: + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: noir-wasm + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Build noir_js_types + run: yarn workspace @noir-lang/types build + + - name: Build noir_wasm + run: ./.github/scripts/noir-wasm-build.sh + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: noir_wasm + path: | + ./compiler/wasm/dist + ./compiler/wasm/build + retention-days: 3 + + build-acvm-js: + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + + - uses: Swatinem/rust-cache@v2 + with: + key: acvm-js + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Build acvm_js + run: ./.github/scripts/acvm_js-build.sh + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: acvm-js + path: | + ./acvm-repo/acvm_js/nodejs + ./acvm-repo/acvm_js/web + retention-days: 3 + + test-acvm_js-node: + needs: [build-acvm-js] + name: ACVM JS (Node.js) + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Set up test environment + uses: ./.github/actions/setup + + - name: Run node tests + run: yarn workspace @noir-lang/acvm_js test + + test-acvm_js-browser: + needs: [build-acvm-js] + name: ACVM JS (Browser) + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Set up test environment + uses: ./.github/actions/setup + + - name: Install Playwright + uses: ./.github/actions/install-playwright + + - name: Run browser tests + run: yarn workspace @noir-lang/acvm_js test:browser + + test-noirc-abi: + needs: [build-noirc-abi] + name: noirc_abi + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Download wasm package artifact + uses: actions/download-artifact@v4 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Run node tests + run: yarn workspace @noir-lang/noirc_abi test + + - name: Install Playwright + uses: ./.github/actions/install-playwright + + - name: Run browser tests + run: yarn workspace @noir-lang/noirc_abi test:browser + + test-noir-js: + needs: [build-nargo, build-acvm-js, build-noirc-abi] + name: Noir JS + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Download wasm package artifact + uses: actions/download-artifact@v4 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Build noir_js_types + run: yarn workspace @noir-lang/types build + + - name: Run noir_js tests + run: | + yarn workspace @noir-lang/noir_js build + yarn workspace @noir-lang/noir_js test + + test-noir-wasm: + needs: [build-noir-wasm, build-nargo] + name: noir_wasm + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Download wasm package artifact + uses: actions/download-artifact@v4 + with: + name: noir_wasm + path: ./compiler/wasm + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - 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)" + + - name: Build fixtures + run: yarn workspace @noir-lang/noir_wasm test:build_fixtures + + - name: Install Playwright + uses: ./.github/actions/install-playwright + + - name: Run node tests + run: yarn workspace @noir-lang/noir_wasm test:node + + - name: Run browser tests + run: yarn workspace @noir-lang/noir_wasm test:browser + + test-noir-codegen: + needs: [build-acvm-js, build-noirc-abi, build-nargo] + name: noir_codegen + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v4 + with: + name: nargo + path: ./nargo + + - name: Download acvm_js package artifact + uses: actions/download-artifact@v4 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Download noirc_abi package artifact + uses: actions/download-artifact@v4 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Build noir_js_types + run: yarn workspace @noir-lang/types build + + - name: Build noir_js + run: yarn workspace @noir-lang/noir_js build + + - name: Run noir_codegen tests + run: yarn workspace @noir-lang/noir_codegen test + + test-integration-node: + name: Integration Tests (Node) + runs-on: ubuntu-22.04 + needs: [build-acvm-js, build-noir-wasm, build-nargo, build-noirc-abi] + timeout-minutes: 30 + + steps: + - 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: + name: nargo + path: ./nargo + + - name: Download acvm_js package artifact + uses: actions/download-artifact@v4 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Download noir_wasm package artifact + uses: actions/download-artifact@v4 + with: + name: noir_wasm + path: ./compiler/wasm + + - name: Download noirc_abi package artifact + uses: actions/download-artifact@v4 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Set nargo on PATH + run: | + nargo_binary="${{ github.workspace }}/nargo/nargo" + chmod +x $nargo_binary + echo "$(dirname $nargo_binary)" >> $GITHUB_PATH + export PATH="$PATH:$(dirname $nargo_binary)" + nargo -V + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Setup `integration-tests` + run: | + # Note the lack of spaces between package names. + PACKAGES_TO_BUILD="@noir-lang/types,@noir-lang/noir_js" + yarn workspaces foreach -vtp --from "{$PACKAGES_TO_BUILD}" run build + + - name: Run `integration-tests` + working-directory: ./compiler/integration-tests + run: | + yarn test:node + + test-integration-browser: + name: Integration Tests (Browser) + runs-on: ubuntu-22.04 + needs: [build-acvm-js, build-noir-wasm, build-noirc-abi] + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download acvm_js package artifact + uses: actions/download-artifact@v4 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Download noir_wasm package artifact + uses: actions/download-artifact@v4 + with: + name: noir_wasm + path: ./compiler/wasm + + - name: Download noirc_abi package artifact + uses: actions/download-artifact@v4 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Install Playwright + uses: ./.github/actions/install-playwright + + - name: Setup `integration-tests` + run: | + # Note the lack of spaces between package names. + PACKAGES_TO_BUILD="@noir-lang/types,@noir-lang/noir_js" + yarn workspaces foreach -vtp --from "{$PACKAGES_TO_BUILD}" run build + + - name: Run `integration-tests` + working-directory: ./compiler/integration-tests + run: | + yarn test:browser + + test-examples: + name: Example scripts + runs-on: ubuntu-22.04 + needs: [build-nargo] + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1.2.0 + with: + version: nightly-8660e5b941fe7f4d67e246cfd3dafea330fb53b1 + + + - 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 + + critical-library-list: + name: Load critical library list + runs-on: ubuntu-22.04 + outputs: + libraries: ${{ steps.get_critical_libraries.outputs.libraries }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build list of libraries + id: get_critical_libraries + run: | + LIBRARIES=$(grep -Po "^https://github.com/\K.+" ./CRITICAL_NOIR_LIBRARIES | jq -R -s -c 'split("\n") | map(select(. != "")) | map({ repo: ., path: ""})') + echo "libraries=$LIBRARIES" + echo "libraries=$LIBRARIES" >> $GITHUB_OUTPUT + env: + GH_TOKEN: ${{ github.token }} + + external-repo-checks: + needs: [build-nargo, critical-library-list] + runs-on: ubuntu-22.04 + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + project: ${{ fromJson( needs.critical-library-list.outputs.libraries )}} + include: + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/aztec-nr } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-contracts } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/blob } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/parity-lib } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-lib } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/reset-kernel-lib } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/types } + # Use 1 test threads for rollup-lib because each test requires a lot of memory, and multiple ones in parallel exceed the maximum memory limit. + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-lib, nargo_args: "--test-threads 1" } + + name: Check external repo - ${{ matrix.project.repo }}/${{ matrix.project.path }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + path: noir-repo + + - name: Checkout + uses: actions/checkout@v4 + with: + repository: ${{ matrix.project.repo }} + path: test-repo + ref: ${{ matrix.project.ref }} + + - 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: Remove requirements on compiler version + working-directory: ./test-repo + run: | + # Github actions seems to not expand "**" in globs by default. + shopt -s globstar + sed -i '/^compiler_version/d' ./**/Nargo.toml + + - name: Run nargo test + working-directory: ./test-repo/${{ matrix.project.path }} + run: | + output_file=${{ github.workspace }}/noir-repo/.github/critical_libraries_status/${{ matrix.project.repo }}/${{ matrix.project.path }}.actual.jsonl + nargo test --silence-warnings --skip-brillig-constraints-check --format json ${{ matrix.project.nargo_args }} | tee $output_file + if [ ! -s $output_file ]; then + # The file is empty so we delete it to signal that `nargo test` failed before it could run any tests + rm -f $output_file + fi + env: + NARGO_IGNORE_TEST_FAILURES_FROM_FOREIGN_CALLS: true + + - name: Compare test results + working-directory: ./noir-repo + run: .github/scripts/check_test_results.sh .github/critical_libraries_status/${{ matrix.project.repo }}/${{ matrix.project.path }}.failures.jsonl .github/critical_libraries_status/${{ matrix.project.repo }}/${{ matrix.project.path }}.actual.jsonl + + # This is a job which depends on all test jobs and reports the overall status. + # This allows us to add/remove test jobs without having to update the required workflows. + tests-end: + name: End + runs-on: ubuntu-22.04 + # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. + if: ${{ always() }} + needs: + - yarn-lock + - test-acvm_js-node + - test-acvm_js-browser + - test-noirc-abi + - test-noir-js + - test-noir-wasm + - test-noir-codegen + - test-integration-node + - test-integration-browser + - test-examples + + steps: + - name: Report overall success + run: | + if [[ $FAIL == true ]]; then + exit 1 + else + exit 0 + fi + env: + # We treat any skipped or failing jobs as a failure for the workflow as a whole. + FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }} diff --git a/.github/workflows/test-rust-workspace-msrv.yml b/.github/workflows/test-rust-workspace-msrv.yml new file mode 100644 index 00000000000..f4fbbf79d89 --- /dev/null +++ b/.github/workflows/test-rust-workspace-msrv.yml @@ -0,0 +1,131 @@ +name: Test (MSRV check) + +# TL;DR https://github.com/noir-lang/noir/issues/4384 +# +# This workflow acts to ensure that we can publish to crates.io, we need this extra check as libraries don't respect the Cargo.lock file committed in this repository. +# We must then always be able to build the workspace using the latest versions of all of our dependencies, so we explicitly update them and build in this workflow. + +on: + schedule: + # Run a nightly check at 2 AM UTC + - cron: "0 2 * * *" + push: + branches: + - master + +# This will cancel previous runs when a branch or PR is updated +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + build-test-artifacts: + name: Build test artifacts + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + with: + targets: x86_64-unknown-linux-gnu + + # We force the ACVM crate and all of its dependencies to update their dependencies + # This ensures that we'll be able to build the crates when they're being published. + - name: Update Cargo.lock + run: | + cargo update --package acvm --aggressive + cargo update --package bn254_blackbox_solver --aggressive + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu-msrv-check + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Install nextest + uses: taiki-e/install-action@v2 + with: + tool: nextest@0.9.67 + + - name: Build and archive tests + run: cargo nextest archive --workspace --release --archive-file nextest-archive.tar.zst + + - name: Upload archive to workflow + uses: actions/upload-artifact@v4 + with: + name: nextest-archive + path: nextest-archive.tar.zst + + run-tests: + name: "Run tests (partition ${{matrix.partition}})" + runs-on: ubuntu-22.04 + needs: [build-test-artifacts] + strategy: + fail-fast: false + matrix: + partition: [1, 2, 3, 4] + steps: + - uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + with: + targets: x86_64-unknown-linux-gnu + + - name: Install nextest + uses: taiki-e/install-action@v2 + with: + tool: nextest@0.9.67 + + - name: Download archive + uses: actions/download-artifact@v4 + with: + name: nextest-archive + - name: Run tests + run: | + RUST_MIN_STACK=8388608 \ + cargo nextest run --archive-file nextest-archive.tar.zst \ + --partition count:${{ matrix.partition }}/4 \ + --no-fail-fast + + # This is a job which depends on all test jobs and reports the overall status. + # This allows us to add/remove test jobs without having to update the required workflows. + tests-end: + name: Rust End + runs-on: ubuntu-22.04 + # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. + if: ${{ always() }} + needs: + - run-tests + + steps: + - name: Report overall success + run: | + if [[ $FAIL == true ]]; then + exit 1 + else + exit 0 + 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, '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 + if: ${{ failure() }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WORKFLOW_NAME: ${{ github.workflow }} + WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + update_existing: true + filename: .github/ACVM_NOT_PUBLISHABLE.md diff --git a/.github/workflows/test-rust-workspace.yml b/.github/workflows/test-rust-workspace.yml new file mode 100644 index 00000000000..5d8abbc3e55 --- /dev/null +++ b/.github/workflows/test-rust-workspace.yml @@ -0,0 +1,102 @@ +name: Test + +on: + pull_request: + merge_group: + push: + branches: + - master + +# This will cancel previous runs when a branch or PR is updated +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + build-test-artifacts: + name: Build test artifacts + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + with: + targets: x86_64-unknown-linux-gnu + + - uses: Swatinem/rust-cache@v2 + with: + key: x86_64-unknown-linux-gnu + cache-on-failure: true + save-if: ${{ github.event_name != 'merge_group' }} + + - name: Install nextest + uses: taiki-e/install-action@v2 + with: + tool: nextest@0.9.67 + + - name: Build and archive tests + run: cargo nextest archive --workspace --release --archive-file nextest-archive.tar.zst + + - name: Upload archive to workflow + uses: actions/upload-artifact@v4 + with: + name: nextest-archive + path: nextest-archive.tar.zst + + run-tests: + name: "Run tests (partition ${{matrix.partition}})" + runs-on: ubuntu-22.04 + needs: [build-test-artifacts] + strategy: + fail-fast: false + matrix: + partition: [1, 2, 3, 4] + steps: + - uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.75.0 + with: + targets: x86_64-unknown-linux-gnu + + - name: Install nextest + uses: taiki-e/install-action@v2 + with: + tool: nextest@0.9.67 + + - name: Download archive + uses: actions/download-artifact@v4 + with: + name: nextest-archive + - name: Run tests + run: | + RUST_MIN_STACK=8388608 \ + cargo nextest run --archive-file nextest-archive.tar.zst \ + --partition count:${{ matrix.partition }}/4 \ + --no-fail-fast + + # This is a job which depends on all test jobs and reports the overall status. + # This allows us to add/remove test jobs without having to update the required workflows. + tests-end: + name: Rust End + runs-on: ubuntu-22.04 + # We want this job to always run (even if the dependant jobs fail) as we want this job to fail rather than skipping. + if: ${{ always() }} + needs: + - run-tests + + steps: + - name: Report overall success + run: | + if [[ $FAIL == true ]]; then + exit 1 + else + exit 0 + 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') }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..9bfb8a89331 --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +/target +.DS_Store +examples/**/target/ +examples/9 +node_modules +pkg/ +.idea + +# Yarn +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# Noir.js +tooling/noir_js/lib + +# Nargo output +*.proof +*.acir +*.acir.sha256 +*.tr +*.pk +*.vk +**/Verifier.toml +**/contract +**/target +!test_programs/acir_artifacts/*/target +!test_programs/acir_artifacts/*/target/witness.gz +!compiler/wasm/noir-script/target + +gates_report.json +gates_report_brillig.json +gates_report_brillig_execution.json +compilation_report.json +execution_report.json + +# Github Actions scratch space +# This gives a location to download artifacts into the repository in CI without making git dirty. +libbarretenberg-wasm32 + +# Wasm build atifacts +compiler/wasm/nodejs +compiler/wasm/web +tooling/noirc_abi_wasm/nodejs +tooling/noirc_abi_wasm/web +tooling/noir_js/lib + +# docs autogen build +/docs/docs/noir_js/reference/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000000..052c0657b3b --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "parser": "typescript", + "printWidth": 120, + "singleQuote": true, + "trailingComma": "all" +} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000000..fd6cef7047a --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "1.0.0-beta.1" +} diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000000..c13d3e328d4 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,2 @@ +edition = "2018" +use_small_heuristics = "Max" diff --git a/.tokeignore b/.tokeignore new file mode 100644 index 00000000000..58aa2c9706a --- /dev/null +++ b/.tokeignore @@ -0,0 +1,9 @@ +docs +scripts + +# config files +*.toml +*.md +*.json +*.txt +*.config.mjs diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000000..efb17cb0085 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,15 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "mkhl.direnv", + "rust-lang.rust-analyzer", + "redhat.vscode-yaml", + "esbenp.prettier-vscode", + // Spell checking + "streetsidesoftware.code-spell-checker", + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..cd1c5f886df --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "direnv.restart.automatic": true, + "redhat.telemetry.enabled": false, + "yaml.recommendations.show": false, + "yaml.schemas": { + "https://json.schemastore.org/github-workflow.json": "${workspaceRoot}/.github/workflows/*.yml" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "rust-analyzer.server.extraEnv": { "RUSTUP_TOOLCHAIN": "stable" } +} 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/.yarn/plugins/@yarnpkg/plugin-typescript.cjs b/.yarn/plugins/@yarnpkg/plugin-typescript.cjs new file mode 100644 index 00000000000..5c1859e0b90 --- /dev/null +++ b/.yarn/plugins/@yarnpkg/plugin-typescript.cjs @@ -0,0 +1,9 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { +name: "@yarnpkg/plugin-typescript", +factory: function (require) { +var plugin=(()=>{var Ft=Object.create,H=Object.defineProperty,Bt=Object.defineProperties,Kt=Object.getOwnPropertyDescriptor,zt=Object.getOwnPropertyDescriptors,Gt=Object.getOwnPropertyNames,Q=Object.getOwnPropertySymbols,$t=Object.getPrototypeOf,ne=Object.prototype.hasOwnProperty,De=Object.prototype.propertyIsEnumerable;var Re=(e,t,r)=>t in e?H(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,u=(e,t)=>{for(var r in t||(t={}))ne.call(t,r)&&Re(e,r,t[r]);if(Q)for(var r of Q(t))De.call(t,r)&&Re(e,r,t[r]);return e},g=(e,t)=>Bt(e,zt(t)),Lt=e=>H(e,"__esModule",{value:!0});var R=(e,t)=>{var r={};for(var s in e)ne.call(e,s)&&t.indexOf(s)<0&&(r[s]=e[s]);if(e!=null&&Q)for(var s of Q(e))t.indexOf(s)<0&&De.call(e,s)&&(r[s]=e[s]);return r};var I=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Vt=(e,t)=>{for(var r in t)H(e,r,{get:t[r],enumerable:!0})},Qt=(e,t,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Gt(t))!ne.call(e,s)&&s!=="default"&&H(e,s,{get:()=>t[s],enumerable:!(r=Kt(t,s))||r.enumerable});return e},C=e=>Qt(Lt(H(e!=null?Ft($t(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var xe=I(J=>{"use strict";Object.defineProperty(J,"__esModule",{value:!0});function _(e){let t=[...e.caches],r=t.shift();return r===void 0?ve():{get(s,n,a={miss:()=>Promise.resolve()}){return r.get(s,n,a).catch(()=>_({caches:t}).get(s,n,a))},set(s,n){return r.set(s,n).catch(()=>_({caches:t}).set(s,n))},delete(s){return r.delete(s).catch(()=>_({caches:t}).delete(s))},clear(){return r.clear().catch(()=>_({caches:t}).clear())}}}function ve(){return{get(e,t,r={miss:()=>Promise.resolve()}){return t().then(n=>Promise.all([n,r.miss(n)])).then(([n])=>n)},set(e,t){return Promise.resolve(t)},delete(e){return Promise.resolve()},clear(){return Promise.resolve()}}}J.createFallbackableCache=_;J.createNullCache=ve});var Ee=I(($s,qe)=>{qe.exports=xe()});var Te=I(ae=>{"use strict";Object.defineProperty(ae,"__esModule",{value:!0});function Jt(e={serializable:!0}){let t={};return{get(r,s,n={miss:()=>Promise.resolve()}){let a=JSON.stringify(r);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);let o=s(),d=n&&n.miss||(()=>Promise.resolve());return o.then(y=>d(y)).then(()=>o)},set(r,s){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(s):s,Promise.resolve(s)},delete(r){return delete t[JSON.stringify(r)],Promise.resolve()},clear(){return t={},Promise.resolve()}}}ae.createInMemoryCache=Jt});var we=I((Vs,Me)=>{Me.exports=Te()});var Ce=I(M=>{"use strict";Object.defineProperty(M,"__esModule",{value:!0});function Xt(e,t,r){let s={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers(){return e===oe.WithinHeaders?s:{}},queryParameters(){return e===oe.WithinQueryParameters?s:{}}}}function Yt(e){let t=0,r=()=>(t++,new Promise(s=>{setTimeout(()=>{s(e(r))},Math.min(100*t,1e3))}));return e(r)}function ke(e,t=(r,s)=>Promise.resolve()){return Object.assign(e,{wait(r){return ke(e.then(s=>Promise.all([t(s,r),s])).then(s=>s[1]))}})}function Zt(e){let t=e.length-1;for(t;t>0;t--){let r=Math.floor(Math.random()*(t+1)),s=e[t];e[t]=e[r],e[r]=s}return e}function er(e,t){return Object.keys(t!==void 0?t:{}).forEach(r=>{e[r]=t[r](e)}),e}function tr(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}var rr="4.2.0",sr=e=>()=>e.transporter.requester.destroy(),oe={WithinQueryParameters:0,WithinHeaders:1};M.AuthMode=oe;M.addMethods=er;M.createAuth=Xt;M.createRetryablePromise=Yt;M.createWaitablePromise=ke;M.destroy=sr;M.encode=tr;M.shuffle=Zt;M.version=rr});var F=I((Js,Ue)=>{Ue.exports=Ce()});var Ne=I(ie=>{"use strict";Object.defineProperty(ie,"__esModule",{value:!0});var nr={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};ie.MethodEnum=nr});var B=I((Ys,We)=>{We.exports=Ne()});var Ze=I(A=>{"use strict";Object.defineProperty(A,"__esModule",{value:!0});var He=B();function ce(e,t){let r=e||{},s=r.data||{};return Object.keys(r).forEach(n=>{["timeout","headers","queryParameters","data","cacheable"].indexOf(n)===-1&&(s[n]=r[n])}),{data:Object.entries(s).length>0?s:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var X={Read:1,Write:2,Any:3},U={Up:1,Down:2,Timeouted:3},_e=2*60*1e3;function ue(e,t=U.Up){return g(u({},e),{status:t,lastUpdate:Date.now()})}function Fe(e){return e.status===U.Up||Date.now()-e.lastUpdate>_e}function Be(e){return e.status===U.Timeouted&&Date.now()-e.lastUpdate<=_e}function le(e){return{protocol:e.protocol||"https",url:e.url,accept:e.accept||X.Any}}function ar(e,t){return Promise.all(t.map(r=>e.get(r,()=>Promise.resolve(ue(r))))).then(r=>{let s=r.filter(d=>Fe(d)),n=r.filter(d=>Be(d)),a=[...s,...n],o=a.length>0?a.map(d=>le(d)):t;return{getTimeout(d,y){return(n.length===0&&d===0?1:n.length+3+d)*y},statelessHosts:o}})}var or=({isTimedOut:e,status:t})=>!e&&~~t==0,ir=e=>{let t=e.status;return e.isTimedOut||or(e)||~~(t/100)!=2&&~~(t/100)!=4},cr=({status:e})=>~~(e/100)==2,ur=(e,t)=>ir(e)?t.onRetry(e):cr(e)?t.onSucess(e):t.onFail(e);function Qe(e,t,r,s){let n=[],a=$e(r,s),o=Le(e,s),d=r.method,y=r.method!==He.MethodEnum.Get?{}:u(u({},r.data),s.data),b=u(u(u({"x-algolia-agent":e.userAgent.value},e.queryParameters),y),s.queryParameters),f=0,p=(h,S)=>{let O=h.pop();if(O===void 0)throw Ve(de(n));let P={data:a,headers:o,method:d,url:Ge(O,r.path,b),connectTimeout:S(f,e.timeouts.connect),responseTimeout:S(f,s.timeout)},x=j=>{let T={request:P,response:j,host:O,triesLeft:h.length};return n.push(T),T},v={onSucess:j=>Ke(j),onRetry(j){let T=x(j);return j.isTimedOut&&f++,Promise.all([e.logger.info("Retryable failure",pe(T)),e.hostsCache.set(O,ue(O,j.isTimedOut?U.Timeouted:U.Down))]).then(()=>p(h,S))},onFail(j){throw x(j),ze(j,de(n))}};return e.requester.send(P).then(j=>ur(j,v))};return ar(e.hostsCache,t).then(h=>p([...h.statelessHosts].reverse(),h.getTimeout))}function lr(e){let{hostsCache:t,logger:r,requester:s,requestsCache:n,responsesCache:a,timeouts:o,userAgent:d,hosts:y,queryParameters:b,headers:f}=e,p={hostsCache:t,logger:r,requester:s,requestsCache:n,responsesCache:a,timeouts:o,userAgent:d,headers:f,queryParameters:b,hosts:y.map(h=>le(h)),read(h,S){let O=ce(S,p.timeouts.read),P=()=>Qe(p,p.hosts.filter(j=>(j.accept&X.Read)!=0),h,O);if((O.cacheable!==void 0?O.cacheable:h.cacheable)!==!0)return P();let v={request:h,mappedRequestOptions:O,transporter:{queryParameters:p.queryParameters,headers:p.headers}};return p.responsesCache.get(v,()=>p.requestsCache.get(v,()=>p.requestsCache.set(v,P()).then(j=>Promise.all([p.requestsCache.delete(v),j]),j=>Promise.all([p.requestsCache.delete(v),Promise.reject(j)])).then(([j,T])=>T)),{miss:j=>p.responsesCache.set(v,j)})},write(h,S){return Qe(p,p.hosts.filter(O=>(O.accept&X.Write)!=0),h,ce(S,p.timeouts.write))}};return p}function dr(e){let t={value:`Algolia for JavaScript (${e})`,add(r){let s=`; ${r.segment}${r.version!==void 0?` (${r.version})`:""}`;return t.value.indexOf(s)===-1&&(t.value=`${t.value}${s}`),t}};return t}function Ke(e){try{return JSON.parse(e.content)}catch(t){throw Je(t.message,e)}}function ze({content:e,status:t},r){let s=e;try{s=JSON.parse(e).message}catch(n){}return Xe(s,t,r)}function pr(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}function Ge(e,t,r){let s=Ye(r),n=`${e.protocol}://${e.url}/${t.charAt(0)==="/"?t.substr(1):t}`;return s.length&&(n+=`?${s}`),n}function Ye(e){let t=r=>Object.prototype.toString.call(r)==="[object Object]"||Object.prototype.toString.call(r)==="[object Array]";return Object.keys(e).map(r=>pr("%s=%s",r,t(e[r])?JSON.stringify(e[r]):e[r])).join("&")}function $e(e,t){if(e.method===He.MethodEnum.Get||e.data===void 0&&t.data===void 0)return;let r=Array.isArray(e.data)?e.data:u(u({},e.data),t.data);return JSON.stringify(r)}function Le(e,t){let r=u(u({},e.headers),t.headers),s={};return Object.keys(r).forEach(n=>{let a=r[n];s[n.toLowerCase()]=a}),s}function de(e){return e.map(t=>pe(t))}function pe(e){let t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return g(u({},e),{request:g(u({},e.request),{headers:u(u({},e.request.headers),t)})})}function Xe(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}function Je(e,t){return{name:"DeserializationError",message:e,response:t}}function Ve(e){return{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:e}}A.CallEnum=X;A.HostStatusEnum=U;A.createApiError=Xe;A.createDeserializationError=Je;A.createMappedRequestOptions=ce;A.createRetryError=Ve;A.createStatefulHost=ue;A.createStatelessHost=le;A.createTransporter=lr;A.createUserAgent=dr;A.deserializeFailure=ze;A.deserializeSuccess=Ke;A.isStatefulHostTimeouted=Be;A.isStatefulHostUp=Fe;A.serializeData=$e;A.serializeHeaders=Le;A.serializeQueryParameters=Ye;A.serializeUrl=Ge;A.stackFrameWithoutCredentials=pe;A.stackTraceWithoutCredentials=de});var K=I((en,et)=>{et.exports=Ze()});var tt=I(w=>{"use strict";Object.defineProperty(w,"__esModule",{value:!0});var N=F(),mr=K(),z=B(),hr=e=>{let t=e.region||"us",r=N.createAuth(N.AuthMode.WithinHeaders,e.appId,e.apiKey),s=mr.createTransporter(g(u({hosts:[{url:`analytics.${t}.algolia.com`}]},e),{headers:u(g(u({},r.headers()),{"content-type":"application/json"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)})),n=e.appId;return N.addMethods({appId:n,transporter:s},e.methods)},yr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Post,path:"2/abtests",data:t},r),gr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Delete,path:N.encode("2/abtests/%s",t)},r),fr=e=>(t,r)=>e.transporter.read({method:z.MethodEnum.Get,path:N.encode("2/abtests/%s",t)},r),br=e=>t=>e.transporter.read({method:z.MethodEnum.Get,path:"2/abtests"},t),Pr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Post,path:N.encode("2/abtests/%s/stop",t)},r);w.addABTest=yr;w.createAnalyticsClient=hr;w.deleteABTest=gr;w.getABTest=fr;w.getABTests=br;w.stopABTest=Pr});var st=I((rn,rt)=>{rt.exports=tt()});var at=I(G=>{"use strict";Object.defineProperty(G,"__esModule",{value:!0});var me=F(),jr=K(),nt=B(),Or=e=>{let t=e.region||"us",r=me.createAuth(me.AuthMode.WithinHeaders,e.appId,e.apiKey),s=jr.createTransporter(g(u({hosts:[{url:`recommendation.${t}.algolia.com`}]},e),{headers:u(g(u({},r.headers()),{"content-type":"application/json"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)}));return me.addMethods({appId:e.appId,transporter:s},e.methods)},Ir=e=>t=>e.transporter.read({method:nt.MethodEnum.Get,path:"1/strategies/personalization"},t),Ar=e=>(t,r)=>e.transporter.write({method:nt.MethodEnum.Post,path:"1/strategies/personalization",data:t},r);G.createRecommendationClient=Or;G.getPersonalizationStrategy=Ir;G.setPersonalizationStrategy=Ar});var it=I((nn,ot)=>{ot.exports=at()});var jt=I(i=>{"use strict";Object.defineProperty(i,"__esModule",{value:!0});var l=F(),q=K(),m=B(),Sr=require("crypto");function Y(e){let t=r=>e.request(r).then(s=>{if(e.batch!==void 0&&e.batch(s.hits),!e.shouldStop(s))return s.cursor?t({cursor:s.cursor}):t({page:(r.page||0)+1})});return t({})}var Dr=e=>{let t=e.appId,r=l.createAuth(e.authMode!==void 0?e.authMode:l.AuthMode.WithinHeaders,t,e.apiKey),s=q.createTransporter(g(u({hosts:[{url:`${t}-dsn.algolia.net`,accept:q.CallEnum.Read},{url:`${t}.algolia.net`,accept:q.CallEnum.Write}].concat(l.shuffle([{url:`${t}-1.algolianet.com`},{url:`${t}-2.algolianet.com`},{url:`${t}-3.algolianet.com`}]))},e),{headers:u(g(u({},r.headers()),{"content-type":"application/x-www-form-urlencoded"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)})),n={transporter:s,appId:t,addAlgoliaAgent(a,o){s.userAgent.add({segment:a,version:o})},clearCache(){return Promise.all([s.requestsCache.clear(),s.responsesCache.clear()]).then(()=>{})}};return l.addMethods(n,e.methods)};function ct(){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 ut(){return{name:"ObjectNotFoundError",message:"Object not found."}}function lt(){return{name:"ValidUntilNotFoundError",message:"ValidUntil not found in given secured api key."}}var Rr=e=>(t,r)=>{let d=r||{},{queryParameters:s}=d,n=R(d,["queryParameters"]),a=u({acl:t},s!==void 0?{queryParameters:s}:{}),o=(y,b)=>l.createRetryablePromise(f=>$(e)(y.key,b).catch(p=>{if(p.status!==404)throw p;return f()}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:"1/keys",data:a},n),o)},vr=e=>(t,r,s)=>{let n=q.createMappedRequestOptions(s);return n.queryParameters["X-Algolia-User-ID"]=t,e.transporter.write({method:m.MethodEnum.Post,path:"1/clusters/mapping",data:{cluster:r}},n)},xr=e=>(t,r,s)=>e.transporter.write({method:m.MethodEnum.Post,path:"1/clusters/mapping/batch",data:{users:t,cluster:r}},s),Z=e=>(t,r,s)=>{let n=(a,o)=>L(e)(t,{methods:{waitTask:D}}).waitTask(a.taskID,o);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",t),data:{operation:"copy",destination:r}},s),n)},qr=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Rules]})),Er=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Settings]})),Tr=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Synonyms]})),Mr=e=>(t,r)=>{let s=(n,a)=>l.createRetryablePromise(o=>$(e)(t,a).then(o).catch(d=>{if(d.status!==404)throw d}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/keys/%s",t)},r),s)},wr=()=>(e,t)=>{let r=q.serializeQueryParameters(t),s=Sr.createHmac("sha256",e).update(r).digest("hex");return Buffer.from(s+r).toString("base64")},$=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/keys/%s",t)},r),kr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/logs"},t),Cr=()=>e=>{let t=Buffer.from(e,"base64").toString("ascii"),r=/validUntil=(\d+)/,s=t.match(r);if(s===null)throw lt();return parseInt(s[1],10)-Math.round(new Date().getTime()/1e3)},Ur=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping/top"},t),Nr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/clusters/mapping/%s",t)},r),Wr=e=>t=>{let n=t||{},{retrieveMappings:r}=n,s=R(n,["retrieveMappings"]);return r===!0&&(s.getClusters=!0),e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping/pending"},s)},L=e=>(t,r={})=>{let s={transporter:e.transporter,appId:e.appId,indexName:t};return l.addMethods(s,r.methods)},Hr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/keys"},t),_r=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters"},t),Fr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/indexes"},t),Br=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping"},t),Kr=e=>(t,r,s)=>{let n=(a,o)=>L(e)(t,{methods:{waitTask:D}}).waitTask(a.taskID,o);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",t),data:{operation:"move",destination:r}},s),n)},zr=e=>(t,r)=>{let s=(n,a)=>Promise.all(Object.keys(n.taskID).map(o=>L(e)(o,{methods:{waitTask:D}}).waitTask(n.taskID[o],a)));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:"1/indexes/*/batch",data:{requests:t}},r),s)},Gr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:t}},r),$r=e=>(t,r)=>{let s=t.map(n=>g(u({},n),{params:q.serializeQueryParameters(n.params||{})}));return e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/queries",data:{requests:s},cacheable:!0},r)},Lr=e=>(t,r)=>Promise.all(t.map(s=>{let d=s.params,{facetName:n,facetQuery:a}=d,o=R(d,["facetName","facetQuery"]);return L(e)(s.indexName,{methods:{searchForFacetValues:dt}}).searchForFacetValues(n,a,u(u({},r),o))})),Vr=e=>(t,r)=>{let s=q.createMappedRequestOptions(r);return s.queryParameters["X-Algolia-User-ID"]=t,e.transporter.write({method:m.MethodEnum.Delete,path:"1/clusters/mapping"},s)},Qr=e=>(t,r)=>{let s=(n,a)=>l.createRetryablePromise(o=>$(e)(t,a).catch(d=>{if(d.status!==404)throw d;return o()}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/keys/%s/restore",t)},r),s)},Jr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:"1/clusters/mapping/search",data:{query:t}},r),Xr=e=>(t,r)=>{let s=Object.assign({},r),f=r||{},{queryParameters:n}=f,a=R(f,["queryParameters"]),o=n?{queryParameters:n}:{},d=["acl","indexes","referers","restrictSources","queryParameters","description","maxQueriesPerIPPerHour","maxHitsPerQuery"],y=p=>Object.keys(s).filter(h=>d.indexOf(h)!==-1).every(h=>p[h]===s[h]),b=(p,h)=>l.createRetryablePromise(S=>$(e)(t,h).then(O=>y(O)?Promise.resolve():S()));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Put,path:l.encode("1/keys/%s",t),data:o},a),b)},pt=e=>(t,r)=>{let s=(n,a)=>D(e)(n.taskID,a);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/batch",e.indexName),data:{requests:t}},r),s)},Yr=e=>t=>Y(g(u({},t),{shouldStop:r=>r.cursor===void 0,request:r=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/browse",e.indexName),data:r},t)})),Zr=e=>t=>{let r=u({hitsPerPage:1e3},t);return Y(g(u({},r),{shouldStop:s=>s.hits.lengthg(u({},n),{hits:n.hits.map(a=>(delete a._highlightResult,a))}))}}))},es=e=>t=>{let r=u({hitsPerPage:1e3},t);return Y(g(u({},r),{shouldStop:s=>s.hits.lengthg(u({},n),{hits:n.hits.map(a=>(delete a._highlightResult,a))}))}}))},te=e=>(t,r,s)=>{let y=s||{},{batchSize:n}=y,a=R(y,["batchSize"]),o={taskIDs:[],objectIDs:[]},d=(b=0)=>{let f=[],p;for(p=b;p({action:r,body:h})),a).then(h=>(o.objectIDs=o.objectIDs.concat(h.objectIDs),o.taskIDs.push(h.taskID),p++,d(p)))};return l.createWaitablePromise(d(),(b,f)=>Promise.all(b.taskIDs.map(p=>D(e)(p,f))))},ts=e=>t=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/clear",e.indexName)},t),(r,s)=>D(e)(r.taskID,s)),rs=e=>t=>{let a=t||{},{forwardToReplicas:r}=a,s=R(a,["forwardToReplicas"]),n=q.createMappedRequestOptions(s);return r&&(n.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/clear",e.indexName)},n),(o,d)=>D(e)(o.taskID,d))},ss=e=>t=>{let a=t||{},{forwardToReplicas:r}=a,s=R(a,["forwardToReplicas"]),n=q.createMappedRequestOptions(s);return r&&(n.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/clear",e.indexName)},n),(o,d)=>D(e)(o.taskID,d))},ns=e=>(t,r)=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/deleteByQuery",e.indexName),data:t},r),(s,n)=>D(e)(s.taskID,n)),as=e=>t=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s",e.indexName)},t),(r,s)=>D(e)(r.taskID,s)),os=e=>(t,r)=>l.createWaitablePromise(yt(e)([t],r).then(s=>({taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),yt=e=>(t,r)=>{let s=t.map(n=>({objectID:n}));return te(e)(s,k.DeleteObject,r)},is=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s/rules/%s",e.indexName,t)},a),(d,y)=>D(e)(d.taskID,y))},cs=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s/synonyms/%s",e.indexName,t)},a),(d,y)=>D(e)(d.taskID,y))},us=e=>t=>gt(e)(t).then(()=>!0).catch(r=>{if(r.status!==404)throw r;return!1}),ls=e=>(t,r)=>{let y=r||{},{query:s,paginate:n}=y,a=R(y,["query","paginate"]),o=0,d=()=>ft(e)(s||"",g(u({},a),{page:o})).then(b=>{for(let[f,p]of Object.entries(b.hits))if(t(p))return{object:p,position:parseInt(f,10),page:o};if(o++,n===!1||o>=b.nbPages)throw ut();return d()});return d()},ds=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/%s",e.indexName,t)},r),ps=()=>(e,t)=>{for(let[r,s]of Object.entries(e.hits))if(s.objectID===t)return parseInt(r,10);return-1},ms=e=>(t,r)=>{let o=r||{},{attributesToRetrieve:s}=o,n=R(o,["attributesToRetrieve"]),a=t.map(d=>u({indexName:e.indexName,objectID:d},s?{attributesToRetrieve:s}:{}));return e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:a}},n)},hs=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/rules/%s",e.indexName,t)},r),gt=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/settings",e.indexName),data:{getVersion:2}},t),ys=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/synonyms/%s",e.indexName,t)},r),bt=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/task/%s",e.indexName,t.toString())},r),gs=e=>(t,r)=>l.createWaitablePromise(Pt(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),Pt=e=>(t,r)=>{let o=r||{},{createIfNotExists:s}=o,n=R(o,["createIfNotExists"]),a=s?k.PartialUpdateObject:k.PartialUpdateObjectNoCreate;return te(e)(t,a,n)},fs=e=>(t,r)=>{let O=r||{},{safe:s,autoGenerateObjectIDIfNotExist:n,batchSize:a}=O,o=R(O,["safe","autoGenerateObjectIDIfNotExist","batchSize"]),d=(P,x,v,j)=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",P),data:{operation:v,destination:x}},j),(T,V)=>D(e)(T.taskID,V)),y=Math.random().toString(36).substring(7),b=`${e.indexName}_tmp_${y}`,f=he({appId:e.appId,transporter:e.transporter,indexName:b}),p=[],h=d(e.indexName,b,"copy",g(u({},o),{scope:["settings","synonyms","rules"]}));p.push(h);let S=(s?h.wait(o):h).then(()=>{let P=f(t,g(u({},o),{autoGenerateObjectIDIfNotExist:n,batchSize:a}));return p.push(P),s?P.wait(o):P}).then(()=>{let P=d(b,e.indexName,"move",o);return p.push(P),s?P.wait(o):P}).then(()=>Promise.all(p)).then(([P,x,v])=>({objectIDs:x.objectIDs,taskIDs:[P.taskID,...x.taskIDs,v.taskID]}));return l.createWaitablePromise(S,(P,x)=>Promise.all(p.map(v=>v.wait(x))))},bs=e=>(t,r)=>ye(e)(t,g(u({},r),{clearExistingRules:!0})),Ps=e=>(t,r)=>ge(e)(t,g(u({},r),{replaceExistingSynonyms:!0})),js=e=>(t,r)=>l.createWaitablePromise(he(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),he=e=>(t,r)=>{let o=r||{},{autoGenerateObjectIDIfNotExist:s}=o,n=R(o,["autoGenerateObjectIDIfNotExist"]),a=s?k.AddObject:k.UpdateObject;if(a===k.UpdateObject){for(let d of t)if(d.objectID===void 0)return l.createWaitablePromise(Promise.reject(ct()))}return te(e)(t,a,n)},Os=e=>(t,r)=>ye(e)([t],r),ye=e=>(t,r)=>{let d=r||{},{forwardToReplicas:s,clearExistingRules:n}=d,a=R(d,["forwardToReplicas","clearExistingRules"]),o=q.createMappedRequestOptions(a);return s&&(o.queryParameters.forwardToReplicas=1),n&&(o.queryParameters.clearExistingRules=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/batch",e.indexName),data:t},o),(y,b)=>D(e)(y.taskID,b))},Is=e=>(t,r)=>ge(e)([t],r),ge=e=>(t,r)=>{let d=r||{},{forwardToReplicas:s,replaceExistingSynonyms:n}=d,a=R(d,["forwardToReplicas","replaceExistingSynonyms"]),o=q.createMappedRequestOptions(a);return s&&(o.queryParameters.forwardToReplicas=1),n&&(o.queryParameters.replaceExistingSynonyms=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/batch",e.indexName),data:t},o),(y,b)=>D(e)(y.taskID,b))},ft=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r),dt=e=>(t,r,s)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},s),mt=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/search",e.indexName),data:{query:t}},r),ht=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/search",e.indexName),data:{query:t}},r),As=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Put,path:l.encode("1/indexes/%s/settings",e.indexName),data:t},a),(d,y)=>D(e)(d.taskID,y))},D=e=>(t,r)=>l.createRetryablePromise(s=>bt(e)(t,r).then(n=>n.status!=="published"?s():void 0)),Ss={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"},k={AddObject:"addObject",UpdateObject:"updateObject",PartialUpdateObject:"partialUpdateObject",PartialUpdateObjectNoCreate:"partialUpdateObjectNoCreate",DeleteObject:"deleteObject"},ee={Settings:"settings",Synonyms:"synonyms",Rules:"rules"},Ds={None:"none",StopIfEnoughMatches:"stopIfEnoughMatches"},Rs={Synonym:"synonym",OneWaySynonym:"oneWaySynonym",AltCorrection1:"altCorrection1",AltCorrection2:"altCorrection2",Placeholder:"placeholder"};i.ApiKeyACLEnum=Ss;i.BatchActionEnum=k;i.ScopeEnum=ee;i.StrategyEnum=Ds;i.SynonymEnum=Rs;i.addApiKey=Rr;i.assignUserID=vr;i.assignUserIDs=xr;i.batch=pt;i.browseObjects=Yr;i.browseRules=Zr;i.browseSynonyms=es;i.chunkedBatch=te;i.clearObjects=ts;i.clearRules=rs;i.clearSynonyms=ss;i.copyIndex=Z;i.copyRules=qr;i.copySettings=Er;i.copySynonyms=Tr;i.createBrowsablePromise=Y;i.createMissingObjectIDError=ct;i.createObjectNotFoundError=ut;i.createSearchClient=Dr;i.createValidUntilNotFoundError=lt;i.deleteApiKey=Mr;i.deleteBy=ns;i.deleteIndex=as;i.deleteObject=os;i.deleteObjects=yt;i.deleteRule=is;i.deleteSynonym=cs;i.exists=us;i.findObject=ls;i.generateSecuredApiKey=wr;i.getApiKey=$;i.getLogs=kr;i.getObject=ds;i.getObjectPosition=ps;i.getObjects=ms;i.getRule=hs;i.getSecuredApiKeyRemainingValidity=Cr;i.getSettings=gt;i.getSynonym=ys;i.getTask=bt;i.getTopUserIDs=Ur;i.getUserID=Nr;i.hasPendingMappings=Wr;i.initIndex=L;i.listApiKeys=Hr;i.listClusters=_r;i.listIndices=Fr;i.listUserIDs=Br;i.moveIndex=Kr;i.multipleBatch=zr;i.multipleGetObjects=Gr;i.multipleQueries=$r;i.multipleSearchForFacetValues=Lr;i.partialUpdateObject=gs;i.partialUpdateObjects=Pt;i.removeUserID=Vr;i.replaceAllObjects=fs;i.replaceAllRules=bs;i.replaceAllSynonyms=Ps;i.restoreApiKey=Qr;i.saveObject=js;i.saveObjects=he;i.saveRule=Os;i.saveRules=ye;i.saveSynonym=Is;i.saveSynonyms=ge;i.search=ft;i.searchForFacetValues=dt;i.searchRules=mt;i.searchSynonyms=ht;i.searchUserIDs=Jr;i.setSettings=As;i.updateApiKey=Xr;i.waitTask=D});var It=I((on,Ot)=>{Ot.exports=jt()});var At=I(re=>{"use strict";Object.defineProperty(re,"__esModule",{value:!0});function vs(){return{debug(e,t){return Promise.resolve()},info(e,t){return Promise.resolve()},error(e,t){return Promise.resolve()}}}var xs={Debug:1,Info:2,Error:3};re.LogLevelEnum=xs;re.createNullLogger=vs});var Dt=I((un,St)=>{St.exports=At()});var xt=I(fe=>{"use strict";Object.defineProperty(fe,"__esModule",{value:!0});var Rt=require("http"),vt=require("https"),qs=require("url");function Es(){let e={keepAlive:!0},t=new Rt.Agent(e),r=new vt.Agent(e);return{send(s){return new Promise(n=>{let a=qs.parse(s.url),o=a.query===null?a.pathname:`${a.pathname}?${a.query}`,d=u({agent:a.protocol==="https:"?r:t,hostname:a.hostname,path:o,method:s.method,headers:s.headers},a.port!==void 0?{port:a.port||""}:{}),y=(a.protocol==="https:"?vt:Rt).request(d,h=>{let S="";h.on("data",O=>S+=O),h.on("end",()=>{clearTimeout(f),clearTimeout(p),n({status:h.statusCode||0,content:S,isTimedOut:!1})})}),b=(h,S)=>setTimeout(()=>{y.abort(),n({status:0,content:S,isTimedOut:!0})},h*1e3),f=b(s.connectTimeout,"Connection timeout"),p;y.on("error",h=>{clearTimeout(f),clearTimeout(p),n({status:0,content:h.message,isTimedOut:!1})}),y.once("response",()=>{clearTimeout(f),p=b(s.responseTimeout,"Socket timeout")}),s.data!==void 0&&y.write(s.data),y.end()})},destroy(){return t.destroy(),r.destroy(),Promise.resolve()}}}fe.createNodeHttpRequester=Es});var Et=I((dn,qt)=>{qt.exports=xt()});var kt=I((pn,Tt)=>{"use strict";var Mt=Ee(),Ts=we(),W=st(),be=F(),Pe=it(),c=It(),Ms=Dt(),ws=Et(),ks=K();function wt(e,t,r){let s={appId:e,apiKey:t,timeouts:{connect:2,read:5,write:30},requester:ws.createNodeHttpRequester(),logger:Ms.createNullLogger(),responsesCache:Mt.createNullCache(),requestsCache:Mt.createNullCache(),hostsCache:Ts.createInMemoryCache(),userAgent:ks.createUserAgent(be.version).add({segment:"Node.js",version:process.versions.node})};return c.createSearchClient(g(u(u({},s),r),{methods:{search:c.multipleQueries,searchForFacetValues:c.multipleSearchForFacetValues,multipleBatch:c.multipleBatch,multipleGetObjects:c.multipleGetObjects,multipleQueries:c.multipleQueries,copyIndex:c.copyIndex,copySettings:c.copySettings,copyRules:c.copyRules,copySynonyms:c.copySynonyms,moveIndex:c.moveIndex,listIndices:c.listIndices,getLogs:c.getLogs,listClusters:c.listClusters,multipleSearchForFacetValues:c.multipleSearchForFacetValues,getApiKey:c.getApiKey,addApiKey:c.addApiKey,listApiKeys:c.listApiKeys,updateApiKey:c.updateApiKey,deleteApiKey:c.deleteApiKey,restoreApiKey:c.restoreApiKey,assignUserID:c.assignUserID,assignUserIDs:c.assignUserIDs,getUserID:c.getUserID,searchUserIDs:c.searchUserIDs,listUserIDs:c.listUserIDs,getTopUserIDs:c.getTopUserIDs,removeUserID:c.removeUserID,hasPendingMappings:c.hasPendingMappings,generateSecuredApiKey:c.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:c.getSecuredApiKeyRemainingValidity,destroy:be.destroy,initIndex:n=>a=>c.initIndex(n)(a,{methods:{batch:c.batch,delete:c.deleteIndex,getObject:c.getObject,getObjects:c.getObjects,saveObject:c.saveObject,saveObjects:c.saveObjects,search:c.search,searchForFacetValues:c.searchForFacetValues,waitTask:c.waitTask,setSettings:c.setSettings,getSettings:c.getSettings,partialUpdateObject:c.partialUpdateObject,partialUpdateObjects:c.partialUpdateObjects,deleteObject:c.deleteObject,deleteObjects:c.deleteObjects,deleteBy:c.deleteBy,clearObjects:c.clearObjects,browseObjects:c.browseObjects,getObjectPosition:c.getObjectPosition,findObject:c.findObject,exists:c.exists,saveSynonym:c.saveSynonym,saveSynonyms:c.saveSynonyms,getSynonym:c.getSynonym,searchSynonyms:c.searchSynonyms,browseSynonyms:c.browseSynonyms,deleteSynonym:c.deleteSynonym,clearSynonyms:c.clearSynonyms,replaceAllObjects:c.replaceAllObjects,replaceAllSynonyms:c.replaceAllSynonyms,searchRules:c.searchRules,getRule:c.getRule,deleteRule:c.deleteRule,saveRule:c.saveRule,saveRules:c.saveRules,replaceAllRules:c.replaceAllRules,browseRules:c.browseRules,clearRules:c.clearRules}}),initAnalytics:()=>n=>W.createAnalyticsClient(g(u(u({},s),n),{methods:{addABTest:W.addABTest,getABTest:W.getABTest,getABTests:W.getABTests,stopABTest:W.stopABTest,deleteABTest:W.deleteABTest}})),initRecommendation:()=>n=>Pe.createRecommendationClient(g(u(u({},s),n),{methods:{getPersonalizationStrategy:Pe.getPersonalizationStrategy,setPersonalizationStrategy:Pe.setPersonalizationStrategy}}))}}))}wt.version=be.version;Tt.exports=wt});var Ut=I((mn,je)=>{var Ct=kt();je.exports=Ct;je.exports.default=Ct});var Ws={};Vt(Ws,{default:()=>Ks});var Oe=C(require("@yarnpkg/core")),E=C(require("@yarnpkg/core")),Ie=C(require("@yarnpkg/plugin-essentials")),Ht=C(require("semver"));var se=C(require("@yarnpkg/core")),Nt=C(Ut()),Cs="e8e1bd300d860104bb8c58453ffa1eb4",Us="OFCNCOG2CU",Wt=async(e,t)=>{var a;let r=se.structUtils.stringifyIdent(e),n=Ns(t).initIndex("npm-search");try{return((a=(await n.getObject(r,{attributesToRetrieve:["types"]})).types)==null?void 0:a.ts)==="definitely-typed"}catch(o){return!1}},Ns=e=>(0,Nt.default)(Us,Cs,{requester:{async send(r){try{let s=await se.httpUtils.request(r.url,r.data||null,{configuration:e,headers:r.headers});return{content:s.body,isTimedOut:!1,status:s.statusCode}}catch(s){return{content:s.response.body,isTimedOut:!1,status:s.response.statusCode}}}}});var _t=e=>e.scope?`${e.scope}__${e.name}`:`${e.name}`,Hs=async(e,t,r,s)=>{if(r.scope==="types")return;let{project:n}=e,{configuration:a}=n,o=a.makeResolver(),d={project:n,resolver:o,report:new E.ThrowReport};if(!await Wt(r,a))return;let b=_t(r),f=E.structUtils.parseRange(r.range).selector;if(!E.semverUtils.validRange(f)){let P=await o.getCandidates(r,new Map,d);f=E.structUtils.parseRange(P[0].reference).selector}let p=Ht.default.coerce(f);if(p===null)return;let h=`${Ie.suggestUtils.Modifier.CARET}${p.major}`,S=E.structUtils.makeDescriptor(E.structUtils.makeIdent("types",b),h),O=E.miscUtils.mapAndFind(n.workspaces,P=>{var T,V;let x=(T=P.manifest.dependencies.get(r.identHash))==null?void 0:T.descriptorHash,v=(V=P.manifest.devDependencies.get(r.identHash))==null?void 0:V.descriptorHash;if(x!==r.descriptorHash&&v!==r.descriptorHash)return E.miscUtils.mapAndFind.skip;let j=[];for(let Ae of Oe.Manifest.allDependencies){let Se=P.manifest[Ae].get(S.identHash);typeof Se!="undefined"&&j.push([Ae,Se])}return j.length===0?E.miscUtils.mapAndFind.skip:j});if(typeof O!="undefined")for(let[P,x]of O)e.manifest[P].set(x.identHash,x);else{try{if((await o.getCandidates(S,new Map,d)).length===0)return}catch{return}e.manifest[Ie.suggestUtils.Target.DEVELOPMENT].set(S.identHash,S)}},_s=async(e,t,r)=>{if(r.scope==="types")return;let s=_t(r),n=E.structUtils.makeIdent("types",s);for(let a of Oe.Manifest.allDependencies)typeof e.manifest[a].get(n.identHash)!="undefined"&&e.manifest[a].delete(n.identHash)},Fs=(e,t)=>{t.publishConfig&&t.publishConfig.typings&&(t.typings=t.publishConfig.typings),t.publishConfig&&t.publishConfig.types&&(t.types=t.publishConfig.types)},Bs={hooks:{afterWorkspaceDependencyAddition:Hs,afterWorkspaceDependencyRemoval:_s,beforeWorkspacePacking:Fs}},Ks=Bs;return Ws;})(); +return plugin; +} +}; diff --git a/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs b/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs new file mode 100644 index 00000000000..4e89c7c352c --- /dev/null +++ b/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs @@ -0,0 +1,28 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { +name: "@yarnpkg/plugin-workspace-tools", +factory: function (require) { +var plugin=(()=>{var yr=Object.create;var we=Object.defineProperty;var _r=Object.getOwnPropertyDescriptor;var Er=Object.getOwnPropertyNames;var br=Object.getPrototypeOf,xr=Object.prototype.hasOwnProperty;var W=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(r,t)=>(typeof require<"u"?require:r)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+e+'" is not supported')});var q=(e,r)=>()=>(r||e((r={exports:{}}).exports,r),r.exports),Cr=(e,r)=>{for(var t in r)we(e,t,{get:r[t],enumerable:!0})},Je=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of Er(r))!xr.call(e,s)&&s!==t&&we(e,s,{get:()=>r[s],enumerable:!(n=_r(r,s))||n.enumerable});return e};var Be=(e,r,t)=>(t=e!=null?yr(br(e)):{},Je(r||!e||!e.__esModule?we(t,"default",{value:e,enumerable:!0}):t,e)),wr=e=>Je(we({},"__esModule",{value:!0}),e);var ve=q(ee=>{"use strict";ee.isInteger=e=>typeof e=="number"?Number.isInteger(e):typeof e=="string"&&e.trim()!==""?Number.isInteger(Number(e)):!1;ee.find=(e,r)=>e.nodes.find(t=>t.type===r);ee.exceedsLimit=(e,r,t=1,n)=>n===!1||!ee.isInteger(e)||!ee.isInteger(r)?!1:(Number(r)-Number(e))/Number(t)>=n;ee.escapeNode=(e,r=0,t)=>{let n=e.nodes[r];!n||(t&&n.type===t||n.type==="open"||n.type==="close")&&n.escaped!==!0&&(n.value="\\"+n.value,n.escaped=!0)};ee.encloseBrace=e=>e.type!=="brace"?!1:e.commas>>0+e.ranges>>0===0?(e.invalid=!0,!0):!1;ee.isInvalidBrace=e=>e.type!=="brace"?!1:e.invalid===!0||e.dollar?!0:e.commas>>0+e.ranges>>0===0||e.open!==!0||e.close!==!0?(e.invalid=!0,!0):!1;ee.isOpenOrClose=e=>e.type==="open"||e.type==="close"?!0:e.open===!0||e.close===!0;ee.reduce=e=>e.reduce((r,t)=>(t.type==="text"&&r.push(t.value),t.type==="range"&&(t.type="text"),r),[]);ee.flatten=(...e)=>{let r=[],t=n=>{for(let s=0;s{"use strict";var tt=ve();rt.exports=(e,r={})=>{let t=(n,s={})=>{let i=r.escapeInvalid&&tt.isInvalidBrace(s),a=n.invalid===!0&&r.escapeInvalid===!0,c="";if(n.value)return(i||a)&&tt.isOpenOrClose(n)?"\\"+n.value:n.value;if(n.value)return n.value;if(n.nodes)for(let p of n.nodes)c+=t(p);return c};return t(e)}});var st=q((Vn,nt)=>{"use strict";nt.exports=function(e){return typeof e=="number"?e-e===0:typeof e=="string"&&e.trim()!==""?Number.isFinite?Number.isFinite(+e):isFinite(+e):!1}});var ht=q((Jn,pt)=>{"use strict";var at=st(),le=(e,r,t)=>{if(at(e)===!1)throw new TypeError("toRegexRange: expected the first argument to be a number");if(r===void 0||e===r)return String(e);if(at(r)===!1)throw new TypeError("toRegexRange: expected the second argument to be a number.");let n={relaxZeros:!0,...t};typeof n.strictZeros=="boolean"&&(n.relaxZeros=n.strictZeros===!1);let s=String(n.relaxZeros),i=String(n.shorthand),a=String(n.capture),c=String(n.wrap),p=e+":"+r+"="+s+i+a+c;if(le.cache.hasOwnProperty(p))return le.cache[p].result;let m=Math.min(e,r),h=Math.max(e,r);if(Math.abs(m-h)===1){let y=e+"|"+r;return n.capture?`(${y})`:n.wrap===!1?y:`(?:${y})`}let R=ft(e)||ft(r),f={min:e,max:r,a:m,b:h},$=[],_=[];if(R&&(f.isPadded=R,f.maxLen=String(f.max).length),m<0){let y=h<0?Math.abs(h):1;_=it(y,Math.abs(m),f,n),m=f.a=0}return h>=0&&($=it(m,h,f,n)),f.negatives=_,f.positives=$,f.result=Sr(_,$,n),n.capture===!0?f.result=`(${f.result})`:n.wrap!==!1&&$.length+_.length>1&&(f.result=`(?:${f.result})`),le.cache[p]=f,f.result};function Sr(e,r,t){let n=Pe(e,r,"-",!1,t)||[],s=Pe(r,e,"",!1,t)||[],i=Pe(e,r,"-?",!0,t)||[];return n.concat(i).concat(s).join("|")}function vr(e,r){let t=1,n=1,s=ut(e,t),i=new Set([r]);for(;e<=s&&s<=r;)i.add(s),t+=1,s=ut(e,t);for(s=ct(r+1,n)-1;e1&&c.count.pop(),c.count.push(h.count[0]),c.string=c.pattern+lt(c.count),a=m+1;continue}t.isPadded&&(R=Lr(m,t,n)),h.string=R+h.pattern+lt(h.count),i.push(h),a=m+1,c=h}return i}function Pe(e,r,t,n,s){let i=[];for(let a of e){let{string:c}=a;!n&&!ot(r,"string",c)&&i.push(t+c),n&&ot(r,"string",c)&&i.push(t+c)}return i}function $r(e,r){let t=[];for(let n=0;nr?1:r>e?-1:0}function ot(e,r,t){return e.some(n=>n[r]===t)}function ut(e,r){return Number(String(e).slice(0,-r)+"9".repeat(r))}function ct(e,r){return e-e%Math.pow(10,r)}function lt(e){let[r=0,t=""]=e;return t||r>1?`{${r+(t?","+t:"")}}`:""}function kr(e,r,t){return`[${e}${r-e===1?"":"-"}${r}]`}function ft(e){return/^-?(0+)\d/.test(e)}function Lr(e,r,t){if(!r.isPadded)return e;let n=Math.abs(r.maxLen-String(e).length),s=t.relaxZeros!==!1;switch(n){case 0:return"";case 1:return s?"0?":"0";case 2:return s?"0{0,2}":"00";default:return s?`0{0,${n}}`:`0{${n}}`}}le.cache={};le.clearCache=()=>le.cache={};pt.exports=le});var Ue=q((es,Et)=>{"use strict";var Or=W("util"),At=ht(),dt=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),Nr=e=>r=>e===!0?Number(r):String(r),Me=e=>typeof e=="number"||typeof e=="string"&&e!=="",Ae=e=>Number.isInteger(+e),De=e=>{let r=`${e}`,t=-1;if(r[0]==="-"&&(r=r.slice(1)),r==="0")return!1;for(;r[++t]==="0";);return t>0},Ir=(e,r,t)=>typeof e=="string"||typeof r=="string"?!0:t.stringify===!0,Br=(e,r,t)=>{if(r>0){let n=e[0]==="-"?"-":"";n&&(e=e.slice(1)),e=n+e.padStart(n?r-1:r,"0")}return t===!1?String(e):e},gt=(e,r)=>{let t=e[0]==="-"?"-":"";for(t&&(e=e.slice(1),r--);e.length{e.negatives.sort((a,c)=>ac?1:0),e.positives.sort((a,c)=>ac?1:0);let t=r.capture?"":"?:",n="",s="",i;return e.positives.length&&(n=e.positives.join("|")),e.negatives.length&&(s=`-(${t}${e.negatives.join("|")})`),n&&s?i=`${n}|${s}`:i=n||s,r.wrap?`(${t}${i})`:i},mt=(e,r,t,n)=>{if(t)return At(e,r,{wrap:!1,...n});let s=String.fromCharCode(e);if(e===r)return s;let i=String.fromCharCode(r);return`[${s}-${i}]`},Rt=(e,r,t)=>{if(Array.isArray(e)){let n=t.wrap===!0,s=t.capture?"":"?:";return n?`(${s}${e.join("|")})`:e.join("|")}return At(e,r,t)},yt=(...e)=>new RangeError("Invalid range arguments: "+Or.inspect(...e)),_t=(e,r,t)=>{if(t.strictRanges===!0)throw yt([e,r]);return[]},Mr=(e,r)=>{if(r.strictRanges===!0)throw new TypeError(`Expected step "${e}" to be a number`);return[]},Dr=(e,r,t=1,n={})=>{let s=Number(e),i=Number(r);if(!Number.isInteger(s)||!Number.isInteger(i)){if(n.strictRanges===!0)throw yt([e,r]);return[]}s===0&&(s=0),i===0&&(i=0);let a=s>i,c=String(e),p=String(r),m=String(t);t=Math.max(Math.abs(t),1);let h=De(c)||De(p)||De(m),R=h?Math.max(c.length,p.length,m.length):0,f=h===!1&&Ir(e,r,n)===!1,$=n.transform||Nr(f);if(n.toRegex&&t===1)return mt(gt(e,R),gt(r,R),!0,n);let _={negatives:[],positives:[]},y=T=>_[T<0?"negatives":"positives"].push(Math.abs(T)),E=[],S=0;for(;a?s>=i:s<=i;)n.toRegex===!0&&t>1?y(s):E.push(Br($(s,S),R,f)),s=a?s-t:s+t,S++;return n.toRegex===!0?t>1?Pr(_,n):Rt(E,null,{wrap:!1,...n}):E},Ur=(e,r,t=1,n={})=>{if(!Ae(e)&&e.length>1||!Ae(r)&&r.length>1)return _t(e,r,n);let s=n.transform||(f=>String.fromCharCode(f)),i=`${e}`.charCodeAt(0),a=`${r}`.charCodeAt(0),c=i>a,p=Math.min(i,a),m=Math.max(i,a);if(n.toRegex&&t===1)return mt(p,m,!1,n);let h=[],R=0;for(;c?i>=a:i<=a;)h.push(s(i,R)),i=c?i-t:i+t,R++;return n.toRegex===!0?Rt(h,null,{wrap:!1,options:n}):h},$e=(e,r,t,n={})=>{if(r==null&&Me(e))return[e];if(!Me(e)||!Me(r))return _t(e,r,n);if(typeof t=="function")return $e(e,r,1,{transform:t});if(dt(t))return $e(e,r,0,t);let s={...n};return s.capture===!0&&(s.wrap=!0),t=t||s.step||1,Ae(t)?Ae(e)&&Ae(r)?Dr(e,r,t,s):Ur(e,r,Math.max(Math.abs(t),1),s):t!=null&&!dt(t)?Mr(t,s):$e(e,r,1,t)};Et.exports=$e});var Ct=q((ts,xt)=>{"use strict";var Gr=Ue(),bt=ve(),qr=(e,r={})=>{let t=(n,s={})=>{let i=bt.isInvalidBrace(s),a=n.invalid===!0&&r.escapeInvalid===!0,c=i===!0||a===!0,p=r.escapeInvalid===!0?"\\":"",m="";if(n.isOpen===!0||n.isClose===!0)return p+n.value;if(n.type==="open")return c?p+n.value:"(";if(n.type==="close")return c?p+n.value:")";if(n.type==="comma")return n.prev.type==="comma"?"":c?n.value:"|";if(n.value)return n.value;if(n.nodes&&n.ranges>0){let h=bt.reduce(n.nodes),R=Gr(...h,{...r,wrap:!1,toRegex:!0});if(R.length!==0)return h.length>1&&R.length>1?`(${R})`:R}if(n.nodes)for(let h of n.nodes)m+=t(h,n);return m};return t(e)};xt.exports=qr});var vt=q((rs,St)=>{"use strict";var Kr=Ue(),wt=He(),he=ve(),fe=(e="",r="",t=!1)=>{let n=[];if(e=[].concat(e),r=[].concat(r),!r.length)return e;if(!e.length)return t?he.flatten(r).map(s=>`{${s}}`):r;for(let s of e)if(Array.isArray(s))for(let i of s)n.push(fe(i,r,t));else for(let i of r)t===!0&&typeof i=="string"&&(i=`{${i}}`),n.push(Array.isArray(i)?fe(s,i,t):s+i);return he.flatten(n)},Wr=(e,r={})=>{let t=r.rangeLimit===void 0?1e3:r.rangeLimit,n=(s,i={})=>{s.queue=[];let a=i,c=i.queue;for(;a.type!=="brace"&&a.type!=="root"&&a.parent;)a=a.parent,c=a.queue;if(s.invalid||s.dollar){c.push(fe(c.pop(),wt(s,r)));return}if(s.type==="brace"&&s.invalid!==!0&&s.nodes.length===2){c.push(fe(c.pop(),["{}"]));return}if(s.nodes&&s.ranges>0){let R=he.reduce(s.nodes);if(he.exceedsLimit(...R,r.step,t))throw new RangeError("expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.");let f=Kr(...R,r);f.length===0&&(f=wt(s,r)),c.push(fe(c.pop(),f)),s.nodes=[];return}let p=he.encloseBrace(s),m=s.queue,h=s;for(;h.type!=="brace"&&h.type!=="root"&&h.parent;)h=h.parent,m=h.queue;for(let R=0;R{"use strict";Ht.exports={MAX_LENGTH:1024*64,CHAR_0:"0",CHAR_9:"9",CHAR_UPPERCASE_A:"A",CHAR_LOWERCASE_A:"a",CHAR_UPPERCASE_Z:"Z",CHAR_LOWERCASE_Z:"z",CHAR_LEFT_PARENTHESES:"(",CHAR_RIGHT_PARENTHESES:")",CHAR_ASTERISK:"*",CHAR_AMPERSAND:"&",CHAR_AT:"@",CHAR_BACKSLASH:"\\",CHAR_BACKTICK:"`",CHAR_CARRIAGE_RETURN:"\r",CHAR_CIRCUMFLEX_ACCENT:"^",CHAR_COLON:":",CHAR_COMMA:",",CHAR_DOLLAR:"$",CHAR_DOT:".",CHAR_DOUBLE_QUOTE:'"',CHAR_EQUAL:"=",CHAR_EXCLAMATION_MARK:"!",CHAR_FORM_FEED:"\f",CHAR_FORWARD_SLASH:"/",CHAR_HASH:"#",CHAR_HYPHEN_MINUS:"-",CHAR_LEFT_ANGLE_BRACKET:"<",CHAR_LEFT_CURLY_BRACE:"{",CHAR_LEFT_SQUARE_BRACKET:"[",CHAR_LINE_FEED:` +`,CHAR_NO_BREAK_SPACE:"\xA0",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:" ",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\uFEFF"}});var Nt=q((ss,Ot)=>{"use strict";var jr=He(),{MAX_LENGTH:Tt,CHAR_BACKSLASH:Ge,CHAR_BACKTICK:Fr,CHAR_COMMA:Qr,CHAR_DOT:Xr,CHAR_LEFT_PARENTHESES:Zr,CHAR_RIGHT_PARENTHESES:Yr,CHAR_LEFT_CURLY_BRACE:zr,CHAR_RIGHT_CURLY_BRACE:Vr,CHAR_LEFT_SQUARE_BRACKET:kt,CHAR_RIGHT_SQUARE_BRACKET:Lt,CHAR_DOUBLE_QUOTE:Jr,CHAR_SINGLE_QUOTE:en,CHAR_NO_BREAK_SPACE:tn,CHAR_ZERO_WIDTH_NOBREAK_SPACE:rn}=$t(),nn=(e,r={})=>{if(typeof e!="string")throw new TypeError("Expected a string");let t=r||{},n=typeof t.maxLength=="number"?Math.min(Tt,t.maxLength):Tt;if(e.length>n)throw new SyntaxError(`Input length (${e.length}), exceeds max characters (${n})`);let s={type:"root",input:e,nodes:[]},i=[s],a=s,c=s,p=0,m=e.length,h=0,R=0,f,$={},_=()=>e[h++],y=E=>{if(E.type==="text"&&c.type==="dot"&&(c.type="text"),c&&c.type==="text"&&E.type==="text"){c.value+=E.value;return}return a.nodes.push(E),E.parent=a,E.prev=c,c=E,E};for(y({type:"bos"});h0){if(a.ranges>0){a.ranges=0;let E=a.nodes.shift();a.nodes=[E,{type:"text",value:jr(a)}]}y({type:"comma",value:f}),a.commas++;continue}if(f===Xr&&R>0&&a.commas===0){let E=a.nodes;if(R===0||E.length===0){y({type:"text",value:f});continue}if(c.type==="dot"){if(a.range=[],c.value+=f,c.type="range",a.nodes.length!==3&&a.nodes.length!==5){a.invalid=!0,a.ranges=0,c.type="text";continue}a.ranges++,a.args=[];continue}if(c.type==="range"){E.pop();let S=E[E.length-1];S.value+=c.value+f,c=S,a.ranges--;continue}y({type:"dot",value:f});continue}y({type:"text",value:f})}do if(a=i.pop(),a.type!=="root"){a.nodes.forEach(T=>{T.nodes||(T.type==="open"&&(T.isOpen=!0),T.type==="close"&&(T.isClose=!0),T.nodes||(T.type="text"),T.invalid=!0)});let E=i[i.length-1],S=E.nodes.indexOf(a);E.nodes.splice(S,1,...a.nodes)}while(i.length>0);return y({type:"eos"}),s};Ot.exports=nn});var Pt=q((as,Bt)=>{"use strict";var It=He(),sn=Ct(),an=vt(),on=Nt(),Z=(e,r={})=>{let t=[];if(Array.isArray(e))for(let n of e){let s=Z.create(n,r);Array.isArray(s)?t.push(...s):t.push(s)}else t=[].concat(Z.create(e,r));return r&&r.expand===!0&&r.nodupes===!0&&(t=[...new Set(t)]),t};Z.parse=(e,r={})=>on(e,r);Z.stringify=(e,r={})=>It(typeof e=="string"?Z.parse(e,r):e,r);Z.compile=(e,r={})=>(typeof e=="string"&&(e=Z.parse(e,r)),sn(e,r));Z.expand=(e,r={})=>{typeof e=="string"&&(e=Z.parse(e,r));let t=an(e,r);return r.noempty===!0&&(t=t.filter(Boolean)),r.nodupes===!0&&(t=[...new Set(t)]),t};Z.create=(e,r={})=>e===""||e.length<3?[e]:r.expand!==!0?Z.compile(e,r):Z.expand(e,r);Bt.exports=Z});var me=q((is,qt)=>{"use strict";var un=W("path"),se="\\\\/",Mt=`[^${se}]`,ie="\\.",cn="\\+",ln="\\?",Te="\\/",fn="(?=.)",Dt="[^/]",qe=`(?:${Te}|$)`,Ut=`(?:^|${Te})`,Ke=`${ie}{1,2}${qe}`,pn=`(?!${ie})`,hn=`(?!${Ut}${Ke})`,dn=`(?!${ie}{0,1}${qe})`,gn=`(?!${Ke})`,An=`[^.${Te}]`,mn=`${Dt}*?`,Gt={DOT_LITERAL:ie,PLUS_LITERAL:cn,QMARK_LITERAL:ln,SLASH_LITERAL:Te,ONE_CHAR:fn,QMARK:Dt,END_ANCHOR:qe,DOTS_SLASH:Ke,NO_DOT:pn,NO_DOTS:hn,NO_DOT_SLASH:dn,NO_DOTS_SLASH:gn,QMARK_NO_DOT:An,STAR:mn,START_ANCHOR:Ut},Rn={...Gt,SLASH_LITERAL:`[${se}]`,QMARK:Mt,STAR:`${Mt}*?`,DOTS_SLASH:`${ie}{1,2}(?:[${se}]|$)`,NO_DOT:`(?!${ie})`,NO_DOTS:`(?!(?:^|[${se}])${ie}{1,2}(?:[${se}]|$))`,NO_DOT_SLASH:`(?!${ie}{0,1}(?:[${se}]|$))`,NO_DOTS_SLASH:`(?!${ie}{1,2}(?:[${se}]|$))`,QMARK_NO_DOT:`[^.${se}]`,START_ANCHOR:`(?:^|[${se}])`,END_ANCHOR:`(?:[${se}]|$)`},yn={alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};qt.exports={MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:yn,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,SEP:un.sep,extglobChars(e){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${e.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(e){return e===!0?Rn:Gt}}});var Re=q(Q=>{"use strict";var _n=W("path"),En=process.platform==="win32",{REGEX_BACKSLASH:bn,REGEX_REMOVE_BACKSLASH:xn,REGEX_SPECIAL_CHARS:Cn,REGEX_SPECIAL_CHARS_GLOBAL:wn}=me();Q.isObject=e=>e!==null&&typeof e=="object"&&!Array.isArray(e);Q.hasRegexChars=e=>Cn.test(e);Q.isRegexChar=e=>e.length===1&&Q.hasRegexChars(e);Q.escapeRegex=e=>e.replace(wn,"\\$1");Q.toPosixSlashes=e=>e.replace(bn,"/");Q.removeBackslashes=e=>e.replace(xn,r=>r==="\\"?"":r);Q.supportsLookbehinds=()=>{let e=process.version.slice(1).split(".").map(Number);return e.length===3&&e[0]>=9||e[0]===8&&e[1]>=10};Q.isWindows=e=>e&&typeof e.windows=="boolean"?e.windows:En===!0||_n.sep==="\\";Q.escapeLast=(e,r,t)=>{let n=e.lastIndexOf(r,t);return n===-1?e:e[n-1]==="\\"?Q.escapeLast(e,r,n-1):`${e.slice(0,n)}\\${e.slice(n)}`};Q.removePrefix=(e,r={})=>{let t=e;return t.startsWith("./")&&(t=t.slice(2),r.prefix="./"),t};Q.wrapOutput=(e,r={},t={})=>{let n=t.contains?"":"^",s=t.contains?"":"$",i=`${n}(?:${e})${s}`;return r.negated===!0&&(i=`(?:^(?!${i}).*$)`),i}});var Yt=q((us,Zt)=>{"use strict";var Kt=Re(),{CHAR_ASTERISK:We,CHAR_AT:Sn,CHAR_BACKWARD_SLASH:ye,CHAR_COMMA:vn,CHAR_DOT:je,CHAR_EXCLAMATION_MARK:Fe,CHAR_FORWARD_SLASH:Xt,CHAR_LEFT_CURLY_BRACE:Qe,CHAR_LEFT_PARENTHESES:Xe,CHAR_LEFT_SQUARE_BRACKET:Hn,CHAR_PLUS:$n,CHAR_QUESTION_MARK:Wt,CHAR_RIGHT_CURLY_BRACE:Tn,CHAR_RIGHT_PARENTHESES:jt,CHAR_RIGHT_SQUARE_BRACKET:kn}=me(),Ft=e=>e===Xt||e===ye,Qt=e=>{e.isPrefix!==!0&&(e.depth=e.isGlobstar?1/0:1)},Ln=(e,r)=>{let t=r||{},n=e.length-1,s=t.parts===!0||t.scanToEnd===!0,i=[],a=[],c=[],p=e,m=-1,h=0,R=0,f=!1,$=!1,_=!1,y=!1,E=!1,S=!1,T=!1,L=!1,z=!1,I=!1,re=0,K,g,v={value:"",depth:0,isGlob:!1},k=()=>m>=n,l=()=>p.charCodeAt(m+1),H=()=>(K=g,p.charCodeAt(++m));for(;m0&&(B=p.slice(0,h),p=p.slice(h),R-=h),w&&_===!0&&R>0?(w=p.slice(0,R),o=p.slice(R)):_===!0?(w="",o=p):w=p,w&&w!==""&&w!=="/"&&w!==p&&Ft(w.charCodeAt(w.length-1))&&(w=w.slice(0,-1)),t.unescape===!0&&(o&&(o=Kt.removeBackslashes(o)),w&&T===!0&&(w=Kt.removeBackslashes(w)));let u={prefix:B,input:e,start:h,base:w,glob:o,isBrace:f,isBracket:$,isGlob:_,isExtglob:y,isGlobstar:E,negated:L,negatedExtglob:z};if(t.tokens===!0&&(u.maxDepth=0,Ft(g)||a.push(v),u.tokens=a),t.parts===!0||t.tokens===!0){let P;for(let b=0;b{"use strict";var ke=me(),Y=Re(),{MAX_LENGTH:Le,POSIX_REGEX_SOURCE:On,REGEX_NON_SPECIAL_CHARS:Nn,REGEX_SPECIAL_CHARS_BACKREF:In,REPLACEMENTS:zt}=ke,Bn=(e,r)=>{if(typeof r.expandRange=="function")return r.expandRange(...e,r);e.sort();let t=`[${e.join("-")}]`;try{new RegExp(t)}catch{return e.map(s=>Y.escapeRegex(s)).join("..")}return t},de=(e,r)=>`Missing ${e}: "${r}" - use "\\\\${r}" to match literal characters`,Vt=(e,r)=>{if(typeof e!="string")throw new TypeError("Expected a string");e=zt[e]||e;let t={...r},n=typeof t.maxLength=="number"?Math.min(Le,t.maxLength):Le,s=e.length;if(s>n)throw new SyntaxError(`Input length: ${s}, exceeds maximum allowed length: ${n}`);let i={type:"bos",value:"",output:t.prepend||""},a=[i],c=t.capture?"":"?:",p=Y.isWindows(r),m=ke.globChars(p),h=ke.extglobChars(m),{DOT_LITERAL:R,PLUS_LITERAL:f,SLASH_LITERAL:$,ONE_CHAR:_,DOTS_SLASH:y,NO_DOT:E,NO_DOT_SLASH:S,NO_DOTS_SLASH:T,QMARK:L,QMARK_NO_DOT:z,STAR:I,START_ANCHOR:re}=m,K=A=>`(${c}(?:(?!${re}${A.dot?y:R}).)*?)`,g=t.dot?"":E,v=t.dot?L:z,k=t.bash===!0?K(t):I;t.capture&&(k=`(${k})`),typeof t.noext=="boolean"&&(t.noextglob=t.noext);let l={input:e,index:-1,start:0,dot:t.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:a};e=Y.removePrefix(e,l),s=e.length;let H=[],w=[],B=[],o=i,u,P=()=>l.index===s-1,b=l.peek=(A=1)=>e[l.index+A],V=l.advance=()=>e[++l.index]||"",J=()=>e.slice(l.index+1),X=(A="",O=0)=>{l.consumed+=A,l.index+=O},Ee=A=>{l.output+=A.output!=null?A.output:A.value,X(A.value)},mr=()=>{let A=1;for(;b()==="!"&&(b(2)!=="("||b(3)==="?");)V(),l.start++,A++;return A%2===0?!1:(l.negated=!0,l.start++,!0)},be=A=>{l[A]++,B.push(A)},oe=A=>{l[A]--,B.pop()},C=A=>{if(o.type==="globstar"){let O=l.braces>0&&(A.type==="comma"||A.type==="brace"),d=A.extglob===!0||H.length&&(A.type==="pipe"||A.type==="paren");A.type!=="slash"&&A.type!=="paren"&&!O&&!d&&(l.output=l.output.slice(0,-o.output.length),o.type="star",o.value="*",o.output=k,l.output+=o.output)}if(H.length&&A.type!=="paren"&&(H[H.length-1].inner+=A.value),(A.value||A.output)&&Ee(A),o&&o.type==="text"&&A.type==="text"){o.value+=A.value,o.output=(o.output||"")+A.value;return}A.prev=o,a.push(A),o=A},xe=(A,O)=>{let d={...h[O],conditions:1,inner:""};d.prev=o,d.parens=l.parens,d.output=l.output;let x=(t.capture?"(":"")+d.open;be("parens"),C({type:A,value:O,output:l.output?"":_}),C({type:"paren",extglob:!0,value:V(),output:x}),H.push(d)},Rr=A=>{let O=A.close+(t.capture?")":""),d;if(A.type==="negate"){let x=k;A.inner&&A.inner.length>1&&A.inner.includes("/")&&(x=K(t)),(x!==k||P()||/^\)+$/.test(J()))&&(O=A.close=`)$))${x}`),A.inner.includes("*")&&(d=J())&&/^\.[^\\/.]+$/.test(d)&&(O=A.close=`)${d})${x})`),A.prev.type==="bos"&&(l.negatedExtglob=!0)}C({type:"paren",extglob:!0,value:u,output:O}),oe("parens")};if(t.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(e)){let A=!1,O=e.replace(In,(d,x,M,j,G,Ie)=>j==="\\"?(A=!0,d):j==="?"?x?x+j+(G?L.repeat(G.length):""):Ie===0?v+(G?L.repeat(G.length):""):L.repeat(M.length):j==="."?R.repeat(M.length):j==="*"?x?x+j+(G?k:""):k:x?d:`\\${d}`);return A===!0&&(t.unescape===!0?O=O.replace(/\\/g,""):O=O.replace(/\\+/g,d=>d.length%2===0?"\\\\":d?"\\":"")),O===e&&t.contains===!0?(l.output=e,l):(l.output=Y.wrapOutput(O,l,r),l)}for(;!P();){if(u=V(),u==="\0")continue;if(u==="\\"){let d=b();if(d==="/"&&t.bash!==!0||d==="."||d===";")continue;if(!d){u+="\\",C({type:"text",value:u});continue}let x=/^\\+/.exec(J()),M=0;if(x&&x[0].length>2&&(M=x[0].length,l.index+=M,M%2!==0&&(u+="\\")),t.unescape===!0?u=V():u+=V(),l.brackets===0){C({type:"text",value:u});continue}}if(l.brackets>0&&(u!=="]"||o.value==="["||o.value==="[^")){if(t.posix!==!1&&u===":"){let d=o.value.slice(1);if(d.includes("[")&&(o.posix=!0,d.includes(":"))){let x=o.value.lastIndexOf("["),M=o.value.slice(0,x),j=o.value.slice(x+2),G=On[j];if(G){o.value=M+G,l.backtrack=!0,V(),!i.output&&a.indexOf(o)===1&&(i.output=_);continue}}}(u==="["&&b()!==":"||u==="-"&&b()==="]")&&(u=`\\${u}`),u==="]"&&(o.value==="["||o.value==="[^")&&(u=`\\${u}`),t.posix===!0&&u==="!"&&o.value==="["&&(u="^"),o.value+=u,Ee({value:u});continue}if(l.quotes===1&&u!=='"'){u=Y.escapeRegex(u),o.value+=u,Ee({value:u});continue}if(u==='"'){l.quotes=l.quotes===1?0:1,t.keepQuotes===!0&&C({type:"text",value:u});continue}if(u==="("){be("parens"),C({type:"paren",value:u});continue}if(u===")"){if(l.parens===0&&t.strictBrackets===!0)throw new SyntaxError(de("opening","("));let d=H[H.length-1];if(d&&l.parens===d.parens+1){Rr(H.pop());continue}C({type:"paren",value:u,output:l.parens?")":"\\)"}),oe("parens");continue}if(u==="["){if(t.nobracket===!0||!J().includes("]")){if(t.nobracket!==!0&&t.strictBrackets===!0)throw new SyntaxError(de("closing","]"));u=`\\${u}`}else be("brackets");C({type:"bracket",value:u});continue}if(u==="]"){if(t.nobracket===!0||o&&o.type==="bracket"&&o.value.length===1){C({type:"text",value:u,output:`\\${u}`});continue}if(l.brackets===0){if(t.strictBrackets===!0)throw new SyntaxError(de("opening","["));C({type:"text",value:u,output:`\\${u}`});continue}oe("brackets");let d=o.value.slice(1);if(o.posix!==!0&&d[0]==="^"&&!d.includes("/")&&(u=`/${u}`),o.value+=u,Ee({value:u}),t.literalBrackets===!1||Y.hasRegexChars(d))continue;let x=Y.escapeRegex(o.value);if(l.output=l.output.slice(0,-o.value.length),t.literalBrackets===!0){l.output+=x,o.value=x;continue}o.value=`(${c}${x}|${o.value})`,l.output+=o.value;continue}if(u==="{"&&t.nobrace!==!0){be("braces");let d={type:"brace",value:u,output:"(",outputIndex:l.output.length,tokensIndex:l.tokens.length};w.push(d),C(d);continue}if(u==="}"){let d=w[w.length-1];if(t.nobrace===!0||!d){C({type:"text",value:u,output:u});continue}let x=")";if(d.dots===!0){let M=a.slice(),j=[];for(let G=M.length-1;G>=0&&(a.pop(),M[G].type!=="brace");G--)M[G].type!=="dots"&&j.unshift(M[G].value);x=Bn(j,t),l.backtrack=!0}if(d.comma!==!0&&d.dots!==!0){let M=l.output.slice(0,d.outputIndex),j=l.tokens.slice(d.tokensIndex);d.value=d.output="\\{",u=x="\\}",l.output=M;for(let G of j)l.output+=G.output||G.value}C({type:"brace",value:u,output:x}),oe("braces"),w.pop();continue}if(u==="|"){H.length>0&&H[H.length-1].conditions++,C({type:"text",value:u});continue}if(u===","){let d=u,x=w[w.length-1];x&&B[B.length-1]==="braces"&&(x.comma=!0,d="|"),C({type:"comma",value:u,output:d});continue}if(u==="/"){if(o.type==="dot"&&l.index===l.start+1){l.start=l.index+1,l.consumed="",l.output="",a.pop(),o=i;continue}C({type:"slash",value:u,output:$});continue}if(u==="."){if(l.braces>0&&o.type==="dot"){o.value==="."&&(o.output=R);let d=w[w.length-1];o.type="dots",o.output+=u,o.value+=u,d.dots=!0;continue}if(l.braces+l.parens===0&&o.type!=="bos"&&o.type!=="slash"){C({type:"text",value:u,output:R});continue}C({type:"dot",value:u,output:R});continue}if(u==="?"){if(!(o&&o.value==="(")&&t.noextglob!==!0&&b()==="("&&b(2)!=="?"){xe("qmark",u);continue}if(o&&o.type==="paren"){let x=b(),M=u;if(x==="<"&&!Y.supportsLookbehinds())throw new Error("Node.js v10 or higher is required for regex lookbehinds");(o.value==="("&&!/[!=<:]/.test(x)||x==="<"&&!/<([!=]|\w+>)/.test(J()))&&(M=`\\${u}`),C({type:"text",value:u,output:M});continue}if(t.dot!==!0&&(o.type==="slash"||o.type==="bos")){C({type:"qmark",value:u,output:z});continue}C({type:"qmark",value:u,output:L});continue}if(u==="!"){if(t.noextglob!==!0&&b()==="("&&(b(2)!=="?"||!/[!=<:]/.test(b(3)))){xe("negate",u);continue}if(t.nonegate!==!0&&l.index===0){mr();continue}}if(u==="+"){if(t.noextglob!==!0&&b()==="("&&b(2)!=="?"){xe("plus",u);continue}if(o&&o.value==="("||t.regex===!1){C({type:"plus",value:u,output:f});continue}if(o&&(o.type==="bracket"||o.type==="paren"||o.type==="brace")||l.parens>0){C({type:"plus",value:u});continue}C({type:"plus",value:f});continue}if(u==="@"){if(t.noextglob!==!0&&b()==="("&&b(2)!=="?"){C({type:"at",extglob:!0,value:u,output:""});continue}C({type:"text",value:u});continue}if(u!=="*"){(u==="$"||u==="^")&&(u=`\\${u}`);let d=Nn.exec(J());d&&(u+=d[0],l.index+=d[0].length),C({type:"text",value:u});continue}if(o&&(o.type==="globstar"||o.star===!0)){o.type="star",o.star=!0,o.value+=u,o.output=k,l.backtrack=!0,l.globstar=!0,X(u);continue}let A=J();if(t.noextglob!==!0&&/^\([^?]/.test(A)){xe("star",u);continue}if(o.type==="star"){if(t.noglobstar===!0){X(u);continue}let d=o.prev,x=d.prev,M=d.type==="slash"||d.type==="bos",j=x&&(x.type==="star"||x.type==="globstar");if(t.bash===!0&&(!M||A[0]&&A[0]!=="/")){C({type:"star",value:u,output:""});continue}let G=l.braces>0&&(d.type==="comma"||d.type==="brace"),Ie=H.length&&(d.type==="pipe"||d.type==="paren");if(!M&&d.type!=="paren"&&!G&&!Ie){C({type:"star",value:u,output:""});continue}for(;A.slice(0,3)==="/**";){let Ce=e[l.index+4];if(Ce&&Ce!=="/")break;A=A.slice(3),X("/**",3)}if(d.type==="bos"&&P()){o.type="globstar",o.value+=u,o.output=K(t),l.output=o.output,l.globstar=!0,X(u);continue}if(d.type==="slash"&&d.prev.type!=="bos"&&!j&&P()){l.output=l.output.slice(0,-(d.output+o.output).length),d.output=`(?:${d.output}`,o.type="globstar",o.output=K(t)+(t.strictSlashes?")":"|$)"),o.value+=u,l.globstar=!0,l.output+=d.output+o.output,X(u);continue}if(d.type==="slash"&&d.prev.type!=="bos"&&A[0]==="/"){let Ce=A[1]!==void 0?"|$":"";l.output=l.output.slice(0,-(d.output+o.output).length),d.output=`(?:${d.output}`,o.type="globstar",o.output=`${K(t)}${$}|${$}${Ce})`,o.value+=u,l.output+=d.output+o.output,l.globstar=!0,X(u+V()),C({type:"slash",value:"/",output:""});continue}if(d.type==="bos"&&A[0]==="/"){o.type="globstar",o.value+=u,o.output=`(?:^|${$}|${K(t)}${$})`,l.output=o.output,l.globstar=!0,X(u+V()),C({type:"slash",value:"/",output:""});continue}l.output=l.output.slice(0,-o.output.length),o.type="globstar",o.output=K(t),o.value+=u,l.output+=o.output,l.globstar=!0,X(u);continue}let O={type:"star",value:u,output:k};if(t.bash===!0){O.output=".*?",(o.type==="bos"||o.type==="slash")&&(O.output=g+O.output),C(O);continue}if(o&&(o.type==="bracket"||o.type==="paren")&&t.regex===!0){O.output=u,C(O);continue}(l.index===l.start||o.type==="slash"||o.type==="dot")&&(o.type==="dot"?(l.output+=S,o.output+=S):t.dot===!0?(l.output+=T,o.output+=T):(l.output+=g,o.output+=g),b()!=="*"&&(l.output+=_,o.output+=_)),C(O)}for(;l.brackets>0;){if(t.strictBrackets===!0)throw new SyntaxError(de("closing","]"));l.output=Y.escapeLast(l.output,"["),oe("brackets")}for(;l.parens>0;){if(t.strictBrackets===!0)throw new SyntaxError(de("closing",")"));l.output=Y.escapeLast(l.output,"("),oe("parens")}for(;l.braces>0;){if(t.strictBrackets===!0)throw new SyntaxError(de("closing","}"));l.output=Y.escapeLast(l.output,"{"),oe("braces")}if(t.strictSlashes!==!0&&(o.type==="star"||o.type==="bracket")&&C({type:"maybe_slash",value:"",output:`${$}?`}),l.backtrack===!0){l.output="";for(let A of l.tokens)l.output+=A.output!=null?A.output:A.value,A.suffix&&(l.output+=A.suffix)}return l};Vt.fastpaths=(e,r)=>{let t={...r},n=typeof t.maxLength=="number"?Math.min(Le,t.maxLength):Le,s=e.length;if(s>n)throw new SyntaxError(`Input length: ${s}, exceeds maximum allowed length: ${n}`);e=zt[e]||e;let i=Y.isWindows(r),{DOT_LITERAL:a,SLASH_LITERAL:c,ONE_CHAR:p,DOTS_SLASH:m,NO_DOT:h,NO_DOTS:R,NO_DOTS_SLASH:f,STAR:$,START_ANCHOR:_}=ke.globChars(i),y=t.dot?R:h,E=t.dot?f:h,S=t.capture?"":"?:",T={negated:!1,prefix:""},L=t.bash===!0?".*?":$;t.capture&&(L=`(${L})`);let z=g=>g.noglobstar===!0?L:`(${S}(?:(?!${_}${g.dot?m:a}).)*?)`,I=g=>{switch(g){case"*":return`${y}${p}${L}`;case".*":return`${a}${p}${L}`;case"*.*":return`${y}${L}${a}${p}${L}`;case"*/*":return`${y}${L}${c}${p}${E}${L}`;case"**":return y+z(t);case"**/*":return`(?:${y}${z(t)}${c})?${E}${p}${L}`;case"**/*.*":return`(?:${y}${z(t)}${c})?${E}${L}${a}${p}${L}`;case"**/.*":return`(?:${y}${z(t)}${c})?${a}${p}${L}`;default:{let v=/^(.*?)\.(\w+)$/.exec(g);if(!v)return;let k=I(v[1]);return k?k+a+v[2]:void 0}}},re=Y.removePrefix(e,T),K=I(re);return K&&t.strictSlashes!==!0&&(K+=`${c}?`),K};Jt.exports=Vt});var rr=q((ls,tr)=>{"use strict";var Pn=W("path"),Mn=Yt(),Ze=er(),Ye=Re(),Dn=me(),Un=e=>e&&typeof e=="object"&&!Array.isArray(e),D=(e,r,t=!1)=>{if(Array.isArray(e)){let h=e.map(f=>D(f,r,t));return f=>{for(let $ of h){let _=$(f);if(_)return _}return!1}}let n=Un(e)&&e.tokens&&e.input;if(e===""||typeof e!="string"&&!n)throw new TypeError("Expected pattern to be a non-empty string");let s=r||{},i=Ye.isWindows(r),a=n?D.compileRe(e,r):D.makeRe(e,r,!1,!0),c=a.state;delete a.state;let p=()=>!1;if(s.ignore){let h={...r,ignore:null,onMatch:null,onResult:null};p=D(s.ignore,h,t)}let m=(h,R=!1)=>{let{isMatch:f,match:$,output:_}=D.test(h,a,r,{glob:e,posix:i}),y={glob:e,state:c,regex:a,posix:i,input:h,output:_,match:$,isMatch:f};return typeof s.onResult=="function"&&s.onResult(y),f===!1?(y.isMatch=!1,R?y:!1):p(h)?(typeof s.onIgnore=="function"&&s.onIgnore(y),y.isMatch=!1,R?y:!1):(typeof s.onMatch=="function"&&s.onMatch(y),R?y:!0)};return t&&(m.state=c),m};D.test=(e,r,t,{glob:n,posix:s}={})=>{if(typeof e!="string")throw new TypeError("Expected input to be a string");if(e==="")return{isMatch:!1,output:""};let i=t||{},a=i.format||(s?Ye.toPosixSlashes:null),c=e===n,p=c&&a?a(e):e;return c===!1&&(p=a?a(e):e,c=p===n),(c===!1||i.capture===!0)&&(i.matchBase===!0||i.basename===!0?c=D.matchBase(e,r,t,s):c=r.exec(p)),{isMatch:Boolean(c),match:c,output:p}};D.matchBase=(e,r,t,n=Ye.isWindows(t))=>(r instanceof RegExp?r:D.makeRe(r,t)).test(Pn.basename(e));D.isMatch=(e,r,t)=>D(r,t)(e);D.parse=(e,r)=>Array.isArray(e)?e.map(t=>D.parse(t,r)):Ze(e,{...r,fastpaths:!1});D.scan=(e,r)=>Mn(e,r);D.compileRe=(e,r,t=!1,n=!1)=>{if(t===!0)return e.output;let s=r||{},i=s.contains?"":"^",a=s.contains?"":"$",c=`${i}(?:${e.output})${a}`;e&&e.negated===!0&&(c=`^(?!${c}).*$`);let p=D.toRegex(c,r);return n===!0&&(p.state=e),p};D.makeRe=(e,r={},t=!1,n=!1)=>{if(!e||typeof e!="string")throw new TypeError("Expected a non-empty string");let s={negated:!1,fastpaths:!0};return r.fastpaths!==!1&&(e[0]==="."||e[0]==="*")&&(s.output=Ze.fastpaths(e,r)),s.output||(s=Ze(e,r)),D.compileRe(s,r,t,n)};D.toRegex=(e,r)=>{try{let t=r||{};return new RegExp(e,t.flags||(t.nocase?"i":""))}catch(t){if(r&&r.debug===!0)throw t;return/$^/}};D.constants=Dn;tr.exports=D});var sr=q((fs,nr)=>{"use strict";nr.exports=rr()});var cr=q((ps,ur)=>{"use strict";var ir=W("util"),or=Pt(),ae=sr(),ze=Re(),ar=e=>e===""||e==="./",N=(e,r,t)=>{r=[].concat(r),e=[].concat(e);let n=new Set,s=new Set,i=new Set,a=0,c=h=>{i.add(h.output),t&&t.onResult&&t.onResult(h)};for(let h=0;h!n.has(h));if(t&&m.length===0){if(t.failglob===!0)throw new Error(`No matches found for "${r.join(", ")}"`);if(t.nonull===!0||t.nullglob===!0)return t.unescape?r.map(h=>h.replace(/\\/g,"")):r}return m};N.match=N;N.matcher=(e,r)=>ae(e,r);N.isMatch=(e,r,t)=>ae(r,t)(e);N.any=N.isMatch;N.not=(e,r,t={})=>{r=[].concat(r).map(String);let n=new Set,s=[],a=N(e,r,{...t,onResult:c=>{t.onResult&&t.onResult(c),s.push(c.output)}});for(let c of s)a.includes(c)||n.add(c);return[...n]};N.contains=(e,r,t)=>{if(typeof e!="string")throw new TypeError(`Expected a string: "${ir.inspect(e)}"`);if(Array.isArray(r))return r.some(n=>N.contains(e,n,t));if(typeof r=="string"){if(ar(e)||ar(r))return!1;if(e.includes(r)||e.startsWith("./")&&e.slice(2).includes(r))return!0}return N.isMatch(e,r,{...t,contains:!0})};N.matchKeys=(e,r,t)=>{if(!ze.isObject(e))throw new TypeError("Expected the first argument to be an object");let n=N(Object.keys(e),r,t),s={};for(let i of n)s[i]=e[i];return s};N.some=(e,r,t)=>{let n=[].concat(e);for(let s of[].concat(r)){let i=ae(String(s),t);if(n.some(a=>i(a)))return!0}return!1};N.every=(e,r,t)=>{let n=[].concat(e);for(let s of[].concat(r)){let i=ae(String(s),t);if(!n.every(a=>i(a)))return!1}return!0};N.all=(e,r,t)=>{if(typeof e!="string")throw new TypeError(`Expected a string: "${ir.inspect(e)}"`);return[].concat(r).every(n=>ae(n,t)(e))};N.capture=(e,r,t)=>{let n=ze.isWindows(t),i=ae.makeRe(String(e),{...t,capture:!0}).exec(n?ze.toPosixSlashes(r):r);if(i)return i.slice(1).map(a=>a===void 0?"":a)};N.makeRe=(...e)=>ae.makeRe(...e);N.scan=(...e)=>ae.scan(...e);N.parse=(e,r)=>{let t=[];for(let n of[].concat(e||[]))for(let s of or(String(n),r))t.push(ae.parse(s,r));return t};N.braces=(e,r)=>{if(typeof e!="string")throw new TypeError("Expected a string");return r&&r.nobrace===!0||!/\{.*\}/.test(e)?[e]:or(e,r)};N.braceExpand=(e,r)=>{if(typeof e!="string")throw new TypeError("Expected a string");return N.braces(e,{...r,expand:!0})};ur.exports=N});var fr=q((hs,lr)=>{"use strict";lr.exports=(e,...r)=>new Promise(t=>{t(e(...r))})});var hr=q((ds,Ve)=>{"use strict";var Gn=fr(),pr=e=>{if(e<1)throw new TypeError("Expected `concurrency` to be a number from 1 and up");let r=[],t=0,n=()=>{t--,r.length>0&&r.shift()()},s=(c,p,...m)=>{t++;let h=Gn(c,...m);p(h),h.then(n,n)},i=(c,p,...m)=>{tnew Promise(m=>i(c,m,...p));return Object.defineProperties(a,{activeCount:{get:()=>t},pendingCount:{get:()=>r.length}}),a};Ve.exports=pr;Ve.exports.default=pr});var jn={};Cr(jn,{default:()=>Wn});var Se=W("@yarnpkg/cli"),ne=W("@yarnpkg/core"),et=W("@yarnpkg/core"),ue=W("clipanion"),ce=class extends Se.BaseCommand{constructor(){super(...arguments);this.json=ue.Option.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.production=ue.Option.Boolean("--production",!1,{description:"Only install regular dependencies by omitting dev dependencies"});this.all=ue.Option.Boolean("-A,--all",!1,{description:"Install the entire project"});this.workspaces=ue.Option.Rest()}async execute(){let t=await ne.Configuration.find(this.context.cwd,this.context.plugins),{project:n,workspace:s}=await ne.Project.find(t,this.context.cwd),i=await ne.Cache.find(t);await n.restoreInstallState({restoreResolutions:!1});let a;if(this.all)a=new Set(n.workspaces);else if(this.workspaces.length===0){if(!s)throw new Se.WorkspaceRequiredError(n.cwd,this.context.cwd);a=new Set([s])}else a=new Set(this.workspaces.map(p=>n.getWorkspaceByIdent(et.structUtils.parseIdent(p))));for(let p of a)for(let m of this.production?["dependencies"]:ne.Manifest.hardDependencies)for(let h of p.manifest.getForScope(m).values()){let R=n.tryWorkspaceByDescriptor(h);R!==null&&a.add(R)}for(let p of n.workspaces)a.has(p)?this.production&&p.manifest.devDependencies.clear():(p.manifest.installConfig=p.manifest.installConfig||{},p.manifest.installConfig.selfReferences=!1,p.manifest.dependencies.clear(),p.manifest.devDependencies.clear(),p.manifest.peerDependencies.clear(),p.manifest.scripts.clear());return(await ne.StreamReport.start({configuration:t,json:this.json,stdout:this.context.stdout,includeLogs:!0},async p=>{await n.install({cache:i,report:p,persistProject:!1})})).exitCode()}};ce.paths=[["workspaces","focus"]],ce.usage=ue.Command.Usage({category:"Workspace-related commands",description:"install a single workspace and its dependencies",details:"\n This command will run an install as if the specified workspaces (and all other workspaces they depend on) were the only ones in the project. If no workspaces are explicitly listed, the active one will be assumed.\n\n Note that this command is only very moderately useful when using zero-installs, since the cache will contain all the packages anyway - meaning that the only difference between a full install and a focused install would just be a few extra lines in the `.pnp.cjs` file, at the cost of introducing an extra complexity.\n\n If the `-A,--all` flag is set, the entire project will be installed. Combine with `--production` to replicate the old `yarn install --production`.\n "});var Ne=W("@yarnpkg/cli"),ge=W("@yarnpkg/core"),_e=W("@yarnpkg/core"),F=W("@yarnpkg/core"),gr=W("@yarnpkg/plugin-git"),U=W("clipanion"),Oe=Be(cr()),Ar=Be(hr()),te=Be(W("typanion")),pe=class extends Ne.BaseCommand{constructor(){super(...arguments);this.recursive=U.Option.Boolean("-R,--recursive",!1,{description:"Find packages via dependencies/devDependencies instead of using the workspaces field"});this.from=U.Option.Array("--from",[],{description:"An array of glob pattern idents from which to base any recursion"});this.all=U.Option.Boolean("-A,--all",!1,{description:"Run the command on all workspaces of a project"});this.verbose=U.Option.Boolean("-v,--verbose",!1,{description:"Prefix each output line with the name of the originating workspace"});this.parallel=U.Option.Boolean("-p,--parallel",!1,{description:"Run the commands in parallel"});this.interlaced=U.Option.Boolean("-i,--interlaced",!1,{description:"Print the output of commands in real-time instead of buffering it"});this.jobs=U.Option.String("-j,--jobs",{description:"The maximum number of parallel tasks that the execution will be limited to; or `unlimited`",validator:te.isOneOf([te.isEnum(["unlimited"]),te.applyCascade(te.isNumber(),[te.isInteger(),te.isAtLeast(1)])])});this.topological=U.Option.Boolean("-t,--topological",!1,{description:"Run the command after all workspaces it depends on (regular) have finished"});this.topologicalDev=U.Option.Boolean("--topological-dev",!1,{description:"Run the command after all workspaces it depends on (regular + dev) have finished"});this.include=U.Option.Array("--include",[],{description:"An array of glob pattern idents; only matching workspaces will be traversed"});this.exclude=U.Option.Array("--exclude",[],{description:"An array of glob pattern idents; matching workspaces won't be traversed"});this.publicOnly=U.Option.Boolean("--no-private",{description:"Avoid running the command on private workspaces"});this.since=U.Option.String("--since",{description:"Only include workspaces that have been changed since the specified ref.",tolerateBoolean:!0});this.commandName=U.Option.String();this.args=U.Option.Proxy()}async execute(){let t=await ge.Configuration.find(this.context.cwd,this.context.plugins),{project:n,workspace:s}=await ge.Project.find(t,this.context.cwd);if(!this.all&&!s)throw new Ne.WorkspaceRequiredError(n.cwd,this.context.cwd);await n.restoreInstallState();let i=this.cli.process([this.commandName,...this.args]),a=i.path.length===1&&i.path[0]==="run"&&typeof i.scriptName<"u"?i.scriptName:null;if(i.path.length===0)throw new U.UsageError("Invalid subcommand name for iteration - use the 'run' keyword if you wish to execute a script");let c=this.all?n.topLevelWorkspace:s,p=this.since?Array.from(await gr.gitUtils.fetchChangedWorkspaces({ref:this.since,project:n})):[c,...this.from.length>0?c.getRecursiveWorkspaceChildren():[]],m=g=>Oe.default.isMatch(F.structUtils.stringifyIdent(g.locator),this.from),h=this.from.length>0?p.filter(m):p,R=new Set([...h,...h.map(g=>[...this.recursive?this.since?g.getRecursiveWorkspaceDependents():g.getRecursiveWorkspaceDependencies():g.getRecursiveWorkspaceChildren()]).flat()]),f=[],$=!1;if(a!=null&&a.includes(":")){for(let g of n.workspaces)if(g.manifest.scripts.has(a)&&($=!$,$===!1))break}for(let g of R)a&&!g.manifest.scripts.has(a)&&!$&&!(await ge.scriptUtils.getWorkspaceAccessibleBinaries(g)).has(a)||a===process.env.npm_lifecycle_event&&g.cwd===s.cwd||this.include.length>0&&!Oe.default.isMatch(F.structUtils.stringifyIdent(g.locator),this.include)||this.exclude.length>0&&Oe.default.isMatch(F.structUtils.stringifyIdent(g.locator),this.exclude)||this.publicOnly&&g.manifest.private===!0||f.push(g);let _=this.parallel?this.jobs==="unlimited"?1/0:Number(this.jobs)||Math.ceil(F.nodeUtils.availableParallelism()/2):1,y=_===1?!1:this.parallel,E=y?this.interlaced:!0,S=(0,Ar.default)(_),T=new Map,L=new Set,z=0,I=null,re=!1,K=await _e.StreamReport.start({configuration:t,stdout:this.context.stdout,includePrefix:!1},async g=>{let v=async(k,{commandIndex:l})=>{if(re)return-1;!y&&this.verbose&&l>1&&g.reportSeparator();let H=qn(k,{configuration:t,verbose:this.verbose,commandIndex:l}),[w,B]=dr(g,{prefix:H,interlaced:E}),[o,u]=dr(g,{prefix:H,interlaced:E});try{this.verbose&&g.reportInfo(null,`${H} Process started`);let P=Date.now(),b=await this.cli.run([this.commandName,...this.args],{cwd:k.cwd,stdout:w,stderr:o})||0;w.end(),o.end(),await B,await u;let V=Date.now();if(this.verbose){let J=t.get("enableTimers")?`, completed in ${F.formatUtils.pretty(t,V-P,F.formatUtils.Type.DURATION)}`:"";g.reportInfo(null,`${H} Process exited (exit code ${b})${J}`)}return b===130&&(re=!0,I=b),b}catch(P){throw w.end(),o.end(),await B,await u,P}};for(let k of f)T.set(k.anchoredLocator.locatorHash,k);for(;T.size>0&&!g.hasErrors();){let k=[];for(let[w,B]of T){if(L.has(B.anchoredDescriptor.descriptorHash))continue;let o=!0;if(this.topological||this.topologicalDev){let u=this.topologicalDev?new Map([...B.manifest.dependencies,...B.manifest.devDependencies]):B.manifest.dependencies;for(let P of u.values()){let b=n.tryWorkspaceByDescriptor(P);if(o=b===null||!T.has(b.anchoredLocator.locatorHash),!o)break}}if(!!o&&(L.add(B.anchoredDescriptor.descriptorHash),k.push(S(async()=>{let u=await v(B,{commandIndex:++z});return T.delete(w),L.delete(B.anchoredDescriptor.descriptorHash),u})),!y))break}if(k.length===0){let w=Array.from(T.values()).map(B=>F.structUtils.prettyLocator(t,B.anchoredLocator)).join(", ");g.reportError(_e.MessageName.CYCLIC_DEPENDENCIES,`Dependency cycle detected (${w})`);return}let H=(await Promise.all(k)).find(w=>w!==0);I===null&&(I=typeof H<"u"?1:I),(this.topological||this.topologicalDev)&&typeof H<"u"&&g.reportError(_e.MessageName.UNNAMED,"The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph")}});return I!==null?I:K.exitCode()}};pe.paths=[["workspaces","foreach"]],pe.usage=U.Command.Usage({category:"Workspace-related commands",description:"run a command on all workspaces",details:"\n This command will run a given sub-command on current and all its descendant workspaces. Various flags can alter the exact behavior of the command:\n\n - If `-p,--parallel` is set, the commands will be ran in parallel; they'll by default be limited to a number of parallel tasks roughly equal to half your core number, but that can be overridden via `-j,--jobs`, or disabled by setting `-j unlimited`.\n\n - If `-p,--parallel` and `-i,--interlaced` are both set, Yarn will print the lines from the output as it receives them. If `-i,--interlaced` wasn't set, it would instead buffer the output from each process and print the resulting buffers only after their source processes have exited.\n\n - If `-t,--topological` is set, Yarn will only run the command after all workspaces that it depends on through the `dependencies` field have successfully finished executing. If `--topological-dev` is set, both the `dependencies` and `devDependencies` fields will be considered when figuring out the wait points.\n\n - If `-A,--all` is set, Yarn will run the command on all the workspaces of a project. By default yarn runs the command only on current and all its descendant workspaces.\n\n - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\n\n - If `--from` is set, Yarn will use the packages matching the 'from' glob as the starting point for any recursive search.\n\n - If `--since` is set, Yarn will only run the command on workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\n\n - The command may apply to only some workspaces through the use of `--include` which acts as a whitelist. The `--exclude` flag will do the opposite and will be a list of packages that mustn't execute the script. Both flags accept glob patterns (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n\n Adding the `-v,--verbose` flag will cause Yarn to print more information; in particular the name of the workspace that generated the output will be printed at the front of each line.\n\n If the command is `run` and the script being run does not exist the child workspace will be skipped without error.\n ",examples:[["Publish current and all descendant packages","yarn workspaces foreach npm publish --tolerate-republish"],["Run build script on current and all descendant packages","yarn workspaces foreach run build"],["Run build script on current and all descendant packages in parallel, building package dependencies first","yarn workspaces foreach -pt run build"],["Run build script on several packages and all their dependencies, building dependencies first","yarn workspaces foreach -ptR --from '{workspace-a,workspace-b}' run build"]]});function dr(e,{prefix:r,interlaced:t}){let n=e.createStreamReporter(r),s=new F.miscUtils.DefaultStream;s.pipe(n,{end:!1}),s.on("finish",()=>{n.end()});let i=new Promise(c=>{n.on("finish",()=>{c(s.active)})});if(t)return[s,i];let a=new F.miscUtils.BufferStream;return a.pipe(s,{end:!1}),a.on("finish",()=>{s.end()}),[a,i]}function qn(e,{configuration:r,commandIndex:t,verbose:n}){if(!n)return null;let i=`[${F.structUtils.stringifyIdent(e.locator)}]:`,a=["#2E86AB","#A23B72","#F18F01","#C73E1D","#CCE2A3"],c=a[t%a.length];return F.formatUtils.pretty(r,i,c)}var Kn={commands:[ce,pe]},Wn=Kn;return wr(jn);})(); +/*! + * fill-range + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Licensed under the MIT License. + */ +/*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + */ +/*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + */ +return plugin; +} +}; diff --git a/.yarn/releases/yarn-3.6.3.cjs b/.yarn/releases/yarn-3.6.3.cjs new file mode 100755 index 00000000000..9837c302811 --- /dev/null +++ b/.yarn/releases/yarn-3.6.3.cjs @@ -0,0 +1,874 @@ +#!/usr/bin/env node +/* eslint-disable */ +//prettier-ignore +(()=>{var Dge=Object.create;var lS=Object.defineProperty;var kge=Object.getOwnPropertyDescriptor;var Rge=Object.getOwnPropertyNames;var Fge=Object.getPrototypeOf,Nge=Object.prototype.hasOwnProperty;var J=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+r+'" is not supported')});var Tge=(r,e)=>()=>(r&&(e=r(r=0)),e);var w=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ut=(r,e)=>{for(var t in e)lS(r,t,{get:e[t],enumerable:!0})},Lge=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Rge(e))!Nge.call(r,n)&&n!==t&&lS(r,n,{get:()=>e[n],enumerable:!(i=kge(e,n))||i.enumerable});return r};var Pe=(r,e,t)=>(t=r!=null?Dge(Fge(r)):{},Lge(e||!r||!r.__esModule?lS(t,"default",{value:r,enumerable:!0}):t,r));var PK=w((z7e,xK)=>{xK.exports=vK;vK.sync=ife;var QK=J("fs");function rfe(r,e){var t=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!t||(t=t.split(";"),t.indexOf("")!==-1))return!0;for(var i=0;i{FK.exports=kK;kK.sync=nfe;var DK=J("fs");function kK(r,e,t){DK.stat(r,function(i,n){t(i,i?!1:RK(n,e))})}function nfe(r,e){return RK(DK.statSync(r),e)}function RK(r,e){return r.isFile()&&sfe(r,e)}function sfe(r,e){var t=r.mode,i=r.uid,n=r.gid,s=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),o=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),a=parseInt("100",8),l=parseInt("010",8),c=parseInt("001",8),u=a|l,g=t&c||t&l&&n===o||t&a&&i===s||t&u&&s===0;return g}});var LK=w((Z7e,TK)=>{var X7e=J("fs"),lI;process.platform==="win32"||global.TESTING_WINDOWS?lI=PK():lI=NK();TK.exports=SS;SS.sync=ofe;function SS(r,e,t){if(typeof e=="function"&&(t=e,e={}),!t){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(i,n){SS(r,e||{},function(s,o){s?n(s):i(o)})})}lI(r,e||{},function(i,n){i&&(i.code==="EACCES"||e&&e.ignoreErrors)&&(i=null,n=!1),t(i,n)})}function ofe(r,e){try{return lI.sync(r,e||{})}catch(t){if(e&&e.ignoreErrors||t.code==="EACCES")return!1;throw t}}});var YK=w((_7e,GK)=>{var Dg=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",MK=J("path"),afe=Dg?";":":",OK=LK(),KK=r=>Object.assign(new Error(`not found: ${r}`),{code:"ENOENT"}),UK=(r,e)=>{let t=e.colon||afe,i=r.match(/\//)||Dg&&r.match(/\\/)?[""]:[...Dg?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(t)],n=Dg?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",s=Dg?n.split(t):[""];return Dg&&r.indexOf(".")!==-1&&s[0]!==""&&s.unshift(""),{pathEnv:i,pathExt:s,pathExtExe:n}},HK=(r,e,t)=>{typeof e=="function"&&(t=e,e={}),e||(e={});let{pathEnv:i,pathExt:n,pathExtExe:s}=UK(r,e),o=[],a=c=>new Promise((u,g)=>{if(c===i.length)return e.all&&o.length?u(o):g(KK(r));let f=i[c],h=/^".*"$/.test(f)?f.slice(1,-1):f,p=MK.join(h,r),C=!h&&/^\.[\\\/]/.test(r)?r.slice(0,2)+p:p;u(l(C,c,0))}),l=(c,u,g)=>new Promise((f,h)=>{if(g===n.length)return f(a(u+1));let p=n[g];OK(c+p,{pathExt:s},(C,y)=>{if(!C&&y)if(e.all)o.push(c+p);else return f(c+p);return f(l(c,u,g+1))})});return t?a(0).then(c=>t(null,c),t):a(0)},Afe=(r,e)=>{e=e||{};let{pathEnv:t,pathExt:i,pathExtExe:n}=UK(r,e),s=[];for(let o=0;o{"use strict";var jK=(r={})=>{let e=r.env||process.env;return(r.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(i=>i.toUpperCase()==="PATH")||"Path"};vS.exports=jK;vS.exports.default=jK});var VK=w((eZe,zK)=>{"use strict";var JK=J("path"),lfe=YK(),cfe=qK();function WK(r,e){let t=r.options.env||process.env,i=process.cwd(),n=r.options.cwd!=null,s=n&&process.chdir!==void 0&&!process.chdir.disabled;if(s)try{process.chdir(r.options.cwd)}catch{}let o;try{o=lfe.sync(r.command,{path:t[cfe({env:t})],pathExt:e?JK.delimiter:void 0})}catch{}finally{s&&process.chdir(i)}return o&&(o=JK.resolve(n?r.options.cwd:"",o)),o}function ufe(r){return WK(r)||WK(r,!0)}zK.exports=ufe});var XK=w((tZe,PS)=>{"use strict";var xS=/([()\][%!^"`<>&|;, *?])/g;function gfe(r){return r=r.replace(xS,"^$1"),r}function ffe(r,e){return r=`${r}`,r=r.replace(/(\\*)"/g,'$1$1\\"'),r=r.replace(/(\\*)$/,"$1$1"),r=`"${r}"`,r=r.replace(xS,"^$1"),e&&(r=r.replace(xS,"^$1")),r}PS.exports.command=gfe;PS.exports.argument=ffe});var _K=w((rZe,ZK)=>{"use strict";ZK.exports=/^#!(.*)/});var eU=w((iZe,$K)=>{"use strict";var hfe=_K();$K.exports=(r="")=>{let e=r.match(hfe);if(!e)return null;let[t,i]=e[0].replace(/#! ?/,"").split(" "),n=t.split("/").pop();return n==="env"?i:i?`${n} ${i}`:n}});var rU=w((nZe,tU)=>{"use strict";var DS=J("fs"),pfe=eU();function dfe(r){let t=Buffer.alloc(150),i;try{i=DS.openSync(r,"r"),DS.readSync(i,t,0,150,0),DS.closeSync(i)}catch{}return pfe(t.toString())}tU.exports=dfe});var oU=w((sZe,sU)=>{"use strict";var Cfe=J("path"),iU=VK(),nU=XK(),mfe=rU(),Efe=process.platform==="win32",Ife=/\.(?:com|exe)$/i,yfe=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function wfe(r){r.file=iU(r);let e=r.file&&mfe(r.file);return e?(r.args.unshift(r.file),r.command=e,iU(r)):r.file}function Bfe(r){if(!Efe)return r;let e=wfe(r),t=!Ife.test(e);if(r.options.forceShell||t){let i=yfe.test(e);r.command=Cfe.normalize(r.command),r.command=nU.command(r.command),r.args=r.args.map(s=>nU.argument(s,i));let n=[r.command].concat(r.args).join(" ");r.args=["/d","/s","/c",`"${n}"`],r.command=process.env.comspec||"cmd.exe",r.options.windowsVerbatimArguments=!0}return r}function bfe(r,e,t){e&&!Array.isArray(e)&&(t=e,e=null),e=e?e.slice(0):[],t=Object.assign({},t);let i={command:r,args:e,options:t,file:void 0,original:{command:r,args:e}};return t.shell?i:Bfe(i)}sU.exports=bfe});var lU=w((oZe,AU)=>{"use strict";var kS=process.platform==="win32";function RS(r,e){return Object.assign(new Error(`${e} ${r.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${r.command}`,path:r.command,spawnargs:r.args})}function Qfe(r,e){if(!kS)return;let t=r.emit;r.emit=function(i,n){if(i==="exit"){let s=aU(n,e,"spawn");if(s)return t.call(r,"error",s)}return t.apply(r,arguments)}}function aU(r,e){return kS&&r===1&&!e.file?RS(e.original,"spawn"):null}function Sfe(r,e){return kS&&r===1&&!e.file?RS(e.original,"spawnSync"):null}AU.exports={hookChildProcess:Qfe,verifyENOENT:aU,verifyENOENTSync:Sfe,notFoundError:RS}});var TS=w((aZe,kg)=>{"use strict";var cU=J("child_process"),FS=oU(),NS=lU();function uU(r,e,t){let i=FS(r,e,t),n=cU.spawn(i.command,i.args,i.options);return NS.hookChildProcess(n,i),n}function vfe(r,e,t){let i=FS(r,e,t),n=cU.spawnSync(i.command,i.args,i.options);return n.error=n.error||NS.verifyENOENTSync(n.status,i),n}kg.exports=uU;kg.exports.spawn=uU;kg.exports.sync=vfe;kg.exports._parse=FS;kg.exports._enoent=NS});var fU=w((AZe,gU)=>{"use strict";function xfe(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function Zl(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,Zl)}xfe(Zl,Error);Zl.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,f=1;g>",ie=me(">>",!1),de=">&",_e=me(">&",!1),Pt=">",It=me(">",!1),Mr="<<<",ii=me("<<<",!1),gi="<&",hr=me("<&",!1),fi="<",ni=me("<",!1),Ks=function(m){return{type:"argument",segments:[].concat(...m)}},pr=function(m){return m},Ii="$'",rs=me("$'",!1),fa="'",dA=me("'",!1),cg=function(m){return[{type:"text",text:m}]},is='""',CA=me('""',!1),ha=function(){return{type:"text",text:""}},wp='"',mA=me('"',!1),EA=function(m){return m},wr=function(m){return{type:"arithmetic",arithmetic:m,quoted:!0}},Tl=function(m){return{type:"shell",shell:m,quoted:!0}},ug=function(m){return{type:"variable",...m,quoted:!0}},yo=function(m){return{type:"text",text:m}},gg=function(m){return{type:"arithmetic",arithmetic:m,quoted:!1}},Bp=function(m){return{type:"shell",shell:m,quoted:!1}},bp=function(m){return{type:"variable",...m,quoted:!1}},vr=function(m){return{type:"glob",pattern:m}},se=/^[^']/,wo=Je(["'"],!0,!1),Fn=function(m){return m.join("")},fg=/^[^$"]/,bt=Je(["$",'"'],!0,!1),Ll=`\\ +`,Nn=me(`\\ +`,!1),ns=function(){return""},ss="\\",gt=me("\\",!1),Bo=/^[\\$"`]/,At=Je(["\\","$",'"',"`"],!1,!1),ln=function(m){return m},S="\\a",Lt=me("\\a",!1),hg=function(){return"a"},Ml="\\b",Qp=me("\\b",!1),Sp=function(){return"\b"},vp=/^[Ee]/,xp=Je(["E","e"],!1,!1),Pp=function(){return"\x1B"},G="\\f",yt=me("\\f",!1),IA=function(){return"\f"},zi="\\n",Ol=me("\\n",!1),Xe=function(){return` +`},pa="\\r",pg=me("\\r",!1),ME=function(){return"\r"},Dp="\\t",OE=me("\\t",!1),ar=function(){return" "},Tn="\\v",Kl=me("\\v",!1),kp=function(){return"\v"},Us=/^[\\'"?]/,da=Je(["\\","'",'"',"?"],!1,!1),cn=function(m){return String.fromCharCode(parseInt(m,16))},Le="\\x",dg=me("\\x",!1),Ul="\\u",Hs=me("\\u",!1),Hl="\\U",yA=me("\\U",!1),Cg=function(m){return String.fromCodePoint(parseInt(m,16))},mg=/^[0-7]/,Ca=Je([["0","7"]],!1,!1),ma=/^[0-9a-fA-f]/,rt=Je([["0","9"],["a","f"],["A","f"]],!1,!1),bo=nt(),wA="-",Gl=me("-",!1),Gs="+",Yl=me("+",!1),KE=".",Rp=me(".",!1),Eg=function(m,Q,N){return{type:"number",value:(m==="-"?-1:1)*parseFloat(Q.join("")+"."+N.join(""))}},Fp=function(m,Q){return{type:"number",value:(m==="-"?-1:1)*parseInt(Q.join(""))}},UE=function(m){return{type:"variable",...m}},jl=function(m){return{type:"variable",name:m}},HE=function(m){return m},Ig="*",BA=me("*",!1),Rr="/",GE=me("/",!1),Ys=function(m,Q,N){return{type:Q==="*"?"multiplication":"division",right:N}},js=function(m,Q){return Q.reduce((N,U)=>({left:N,...U}),m)},yg=function(m,Q,N){return{type:Q==="+"?"addition":"subtraction",right:N}},bA="$((",R=me("$((",!1),q="))",Ce=me("))",!1),Ke=function(m){return m},Re="$(",ze=me("$(",!1),dt=function(m){return m},Ft="${",Ln=me("${",!1),JQ=":-",k1=me(":-",!1),R1=function(m,Q){return{name:m,defaultValue:Q}},WQ=":-}",F1=me(":-}",!1),N1=function(m){return{name:m,defaultValue:[]}},zQ=":+",T1=me(":+",!1),L1=function(m,Q){return{name:m,alternativeValue:Q}},VQ=":+}",M1=me(":+}",!1),O1=function(m){return{name:m,alternativeValue:[]}},XQ=function(m){return{name:m}},K1="$",U1=me("$",!1),H1=function(m){return e.isGlobPattern(m)},G1=function(m){return m},ZQ=/^[a-zA-Z0-9_]/,_Q=Je([["a","z"],["A","Z"],["0","9"],"_"],!1,!1),$Q=function(){return L()},eS=/^[$@*?#a-zA-Z0-9_\-]/,tS=Je(["$","@","*","?","#",["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),Y1=/^[(){}<>$|&; \t"']/,wg=Je(["(",")","{","}","<",">","$","|","&",";"," "," ",'"',"'"],!1,!1),rS=/^[<>&; \t"']/,iS=Je(["<",">","&",";"," "," ",'"',"'"],!1,!1),YE=/^[ \t]/,jE=Je([" "," "],!1,!1),b=0,Oe=0,QA=[{line:1,column:1}],d=0,E=[],I=0,k;if("startRule"in e){if(!(e.startRule in i))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');n=i[e.startRule]}function L(){return r.substring(Oe,b)}function Z(){return Et(Oe,b)}function te(m,Q){throw Q=Q!==void 0?Q:Et(Oe,b),Ri([lt(m)],r.substring(Oe,b),Q)}function we(m,Q){throw Q=Q!==void 0?Q:Et(Oe,b),Mn(m,Q)}function me(m,Q){return{type:"literal",text:m,ignoreCase:Q}}function Je(m,Q,N){return{type:"class",parts:m,inverted:Q,ignoreCase:N}}function nt(){return{type:"any"}}function wt(){return{type:"end"}}function lt(m){return{type:"other",description:m}}function it(m){var Q=QA[m],N;if(Q)return Q;for(N=m-1;!QA[N];)N--;for(Q=QA[N],Q={line:Q.line,column:Q.column};Nd&&(d=b,E=[]),E.push(m))}function Mn(m,Q){return new Zl(m,null,null,Q)}function Ri(m,Q,N){return new Zl(Zl.buildMessage(m,Q),m,Q,N)}function SA(){var m,Q;return m=b,Q=Or(),Q===t&&(Q=null),Q!==t&&(Oe=m,Q=s(Q)),m=Q,m}function Or(){var m,Q,N,U,ce;if(m=b,Q=Kr(),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();N!==t?(U=Ea(),U!==t?(ce=os(),ce===t&&(ce=null),ce!==t?(Oe=m,Q=o(Q,U,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;if(m===t)if(m=b,Q=Kr(),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();N!==t?(U=Ea(),U===t&&(U=null),U!==t?(Oe=m,Q=a(Q,U),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;return m}function os(){var m,Q,N,U,ce;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(N=Or(),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=l(N),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t;return m}function Ea(){var m;return r.charCodeAt(b)===59?(m=c,b++):(m=t,I===0&&be(u)),m===t&&(r.charCodeAt(b)===38?(m=g,b++):(m=t,I===0&&be(f))),m}function Kr(){var m,Q,N;return m=b,Q=j1(),Q!==t?(N=fge(),N===t&&(N=null),N!==t?(Oe=m,Q=h(Q,N),m=Q):(b=m,m=t)):(b=m,m=t),m}function fge(){var m,Q,N,U,ce,Se,ht;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(N=hge(),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=Kr(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();Se!==t?(Oe=m,Q=p(N,ce),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;return m}function hge(){var m;return r.substr(b,2)===C?(m=C,b+=2):(m=t,I===0&&be(y)),m===t&&(r.substr(b,2)===B?(m=B,b+=2):(m=t,I===0&&be(v))),m}function j1(){var m,Q,N;return m=b,Q=Cge(),Q!==t?(N=pge(),N===t&&(N=null),N!==t?(Oe=m,Q=D(Q,N),m=Q):(b=m,m=t)):(b=m,m=t),m}function pge(){var m,Q,N,U,ce,Se,ht;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(N=dge(),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=j1(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();Se!==t?(Oe=m,Q=T(N,ce),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;return m}function dge(){var m;return r.substr(b,2)===H?(m=H,b+=2):(m=t,I===0&&be(j)),m===t&&(r.charCodeAt(b)===124?(m=$,b++):(m=t,I===0&&be(V))),m}function qE(){var m,Q,N,U,ce,Se;if(m=b,Q=rK(),Q!==t)if(r.charCodeAt(b)===61?(N=W,b++):(N=t,I===0&&be(_)),N!==t)if(U=W1(),U!==t){for(ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();ce!==t?(Oe=m,Q=A(Q,U),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t;else b=m,m=t;if(m===t)if(m=b,Q=rK(),Q!==t)if(r.charCodeAt(b)===61?(N=W,b++):(N=t,I===0&&be(_)),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=Ae(Q),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t;return m}function Cge(){var m,Q,N,U,ce,Se,ht,Bt,qr,hi,as;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(r.charCodeAt(b)===40?(N=ge,b++):(N=t,I===0&&be(re)),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=Or(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();if(Se!==t)if(r.charCodeAt(b)===41?(ht=M,b++):(ht=t,I===0&&be(F)),ht!==t){for(Bt=[],qr=He();qr!==t;)Bt.push(qr),qr=He();if(Bt!==t){for(qr=[],hi=Np();hi!==t;)qr.push(hi),hi=Np();if(qr!==t){for(hi=[],as=He();as!==t;)hi.push(as),as=He();hi!==t?(Oe=m,Q=ue(ce,qr),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;if(m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t)if(r.charCodeAt(b)===123?(N=pe,b++):(N=t,I===0&&be(ke)),N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t)if(ce=Or(),ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();if(Se!==t)if(r.charCodeAt(b)===125?(ht=Fe,b++):(ht=t,I===0&&be(Ne)),ht!==t){for(Bt=[],qr=He();qr!==t;)Bt.push(qr),qr=He();if(Bt!==t){for(qr=[],hi=Np();hi!==t;)qr.push(hi),hi=Np();if(qr!==t){for(hi=[],as=He();as!==t;)hi.push(as),as=He();hi!==t?(Oe=m,Q=oe(ce,qr),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t}else b=m,m=t;else b=m,m=t;if(m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t){for(N=[],U=qE();U!==t;)N.push(U),U=qE();if(N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();if(U!==t){if(ce=[],Se=J1(),Se!==t)for(;Se!==t;)ce.push(Se),Se=J1();else ce=t;if(ce!==t){for(Se=[],ht=He();ht!==t;)Se.push(ht),ht=He();Se!==t?(Oe=m,Q=le(N,ce),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}else b=m,m=t}else b=m,m=t;if(m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t){if(N=[],U=qE(),U!==t)for(;U!==t;)N.push(U),U=qE();else N=t;if(N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=Be(N),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t}}}return m}function q1(){var m,Q,N,U,ce;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t){if(N=[],U=JE(),U!==t)for(;U!==t;)N.push(U),U=JE();else N=t;if(N!==t){for(U=[],ce=He();ce!==t;)U.push(ce),ce=He();U!==t?(Oe=m,Q=fe(N),m=Q):(b=m,m=t)}else b=m,m=t}else b=m,m=t;return m}function J1(){var m,Q,N;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();if(Q!==t?(N=Np(),N!==t?(Oe=m,Q=ae(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t){for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();Q!==t?(N=JE(),N!==t?(Oe=m,Q=ae(N),m=Q):(b=m,m=t)):(b=m,m=t)}return m}function Np(){var m,Q,N,U,ce;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();return Q!==t?(qe.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(ne)),N===t&&(N=null),N!==t?(U=mge(),U!==t?(ce=JE(),ce!==t?(Oe=m,Q=Y(N,U,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function mge(){var m;return r.substr(b,2)===he?(m=he,b+=2):(m=t,I===0&&be(ie)),m===t&&(r.substr(b,2)===de?(m=de,b+=2):(m=t,I===0&&be(_e)),m===t&&(r.charCodeAt(b)===62?(m=Pt,b++):(m=t,I===0&&be(It)),m===t&&(r.substr(b,3)===Mr?(m=Mr,b+=3):(m=t,I===0&&be(ii)),m===t&&(r.substr(b,2)===gi?(m=gi,b+=2):(m=t,I===0&&be(hr)),m===t&&(r.charCodeAt(b)===60?(m=fi,b++):(m=t,I===0&&be(ni))))))),m}function JE(){var m,Q,N;for(m=b,Q=[],N=He();N!==t;)Q.push(N),N=He();return Q!==t?(N=W1(),N!==t?(Oe=m,Q=ae(N),m=Q):(b=m,m=t)):(b=m,m=t),m}function W1(){var m,Q,N;if(m=b,Q=[],N=z1(),N!==t)for(;N!==t;)Q.push(N),N=z1();else Q=t;return Q!==t&&(Oe=m,Q=Ks(Q)),m=Q,m}function z1(){var m,Q;return m=b,Q=Ege(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q,m===t&&(m=b,Q=Ige(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q,m===t&&(m=b,Q=yge(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q,m===t&&(m=b,Q=wge(),Q!==t&&(Oe=m,Q=pr(Q)),m=Q))),m}function Ege(){var m,Q,N,U;return m=b,r.substr(b,2)===Ii?(Q=Ii,b+=2):(Q=t,I===0&&be(rs)),Q!==t?(N=Qge(),N!==t?(r.charCodeAt(b)===39?(U=fa,b++):(U=t,I===0&&be(dA)),U!==t?(Oe=m,Q=cg(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function Ige(){var m,Q,N,U;return m=b,r.charCodeAt(b)===39?(Q=fa,b++):(Q=t,I===0&&be(dA)),Q!==t?(N=Bge(),N!==t?(r.charCodeAt(b)===39?(U=fa,b++):(U=t,I===0&&be(dA)),U!==t?(Oe=m,Q=cg(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function yge(){var m,Q,N,U;if(m=b,r.substr(b,2)===is?(Q=is,b+=2):(Q=t,I===0&&be(CA)),Q!==t&&(Oe=m,Q=ha()),m=Q,m===t)if(m=b,r.charCodeAt(b)===34?(Q=wp,b++):(Q=t,I===0&&be(mA)),Q!==t){for(N=[],U=V1();U!==t;)N.push(U),U=V1();N!==t?(r.charCodeAt(b)===34?(U=wp,b++):(U=t,I===0&&be(mA)),U!==t?(Oe=m,Q=EA(N),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;return m}function wge(){var m,Q,N;if(m=b,Q=[],N=X1(),N!==t)for(;N!==t;)Q.push(N),N=X1();else Q=t;return Q!==t&&(Oe=m,Q=EA(Q)),m=Q,m}function V1(){var m,Q;return m=b,Q=eK(),Q!==t&&(Oe=m,Q=wr(Q)),m=Q,m===t&&(m=b,Q=tK(),Q!==t&&(Oe=m,Q=Tl(Q)),m=Q,m===t&&(m=b,Q=aS(),Q!==t&&(Oe=m,Q=ug(Q)),m=Q,m===t&&(m=b,Q=bge(),Q!==t&&(Oe=m,Q=yo(Q)),m=Q))),m}function X1(){var m,Q;return m=b,Q=eK(),Q!==t&&(Oe=m,Q=gg(Q)),m=Q,m===t&&(m=b,Q=tK(),Q!==t&&(Oe=m,Q=Bp(Q)),m=Q,m===t&&(m=b,Q=aS(),Q!==t&&(Oe=m,Q=bp(Q)),m=Q,m===t&&(m=b,Q=xge(),Q!==t&&(Oe=m,Q=vr(Q)),m=Q,m===t&&(m=b,Q=vge(),Q!==t&&(Oe=m,Q=yo(Q)),m=Q)))),m}function Bge(){var m,Q,N;for(m=b,Q=[],se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(wo));N!==t;)Q.push(N),se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(wo));return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function bge(){var m,Q,N;if(m=b,Q=[],N=Z1(),N===t&&(fg.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(bt))),N!==t)for(;N!==t;)Q.push(N),N=Z1(),N===t&&(fg.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(bt)));else Q=t;return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function Z1(){var m,Q,N;return m=b,r.substr(b,2)===Ll?(Q=Ll,b+=2):(Q=t,I===0&&be(Nn)),Q!==t&&(Oe=m,Q=ns()),m=Q,m===t&&(m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(Bo.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(At)),N!==t?(Oe=m,Q=ln(N),m=Q):(b=m,m=t)):(b=m,m=t)),m}function Qge(){var m,Q,N;for(m=b,Q=[],N=_1(),N===t&&(se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(wo)));N!==t;)Q.push(N),N=_1(),N===t&&(se.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(wo)));return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function _1(){var m,Q,N;return m=b,r.substr(b,2)===S?(Q=S,b+=2):(Q=t,I===0&&be(Lt)),Q!==t&&(Oe=m,Q=hg()),m=Q,m===t&&(m=b,r.substr(b,2)===Ml?(Q=Ml,b+=2):(Q=t,I===0&&be(Qp)),Q!==t&&(Oe=m,Q=Sp()),m=Q,m===t&&(m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(vp.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(xp)),N!==t?(Oe=m,Q=Pp(),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===G?(Q=G,b+=2):(Q=t,I===0&&be(yt)),Q!==t&&(Oe=m,Q=IA()),m=Q,m===t&&(m=b,r.substr(b,2)===zi?(Q=zi,b+=2):(Q=t,I===0&&be(Ol)),Q!==t&&(Oe=m,Q=Xe()),m=Q,m===t&&(m=b,r.substr(b,2)===pa?(Q=pa,b+=2):(Q=t,I===0&&be(pg)),Q!==t&&(Oe=m,Q=ME()),m=Q,m===t&&(m=b,r.substr(b,2)===Dp?(Q=Dp,b+=2):(Q=t,I===0&&be(OE)),Q!==t&&(Oe=m,Q=ar()),m=Q,m===t&&(m=b,r.substr(b,2)===Tn?(Q=Tn,b+=2):(Q=t,I===0&&be(Kl)),Q!==t&&(Oe=m,Q=kp()),m=Q,m===t&&(m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(Us.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(da)),N!==t?(Oe=m,Q=ln(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=Sge()))))))))),m}function Sge(){var m,Q,N,U,ce,Se,ht,Bt,qr,hi,as,AS;return m=b,r.charCodeAt(b)===92?(Q=ss,b++):(Q=t,I===0&&be(gt)),Q!==t?(N=nS(),N!==t?(Oe=m,Q=cn(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Le?(Q=Le,b+=2):(Q=t,I===0&&be(dg)),Q!==t?(N=b,U=b,ce=nS(),ce!==t?(Se=On(),Se!==t?(ce=[ce,Se],U=ce):(b=U,U=t)):(b=U,U=t),U===t&&(U=nS()),U!==t?N=r.substring(N,b):N=U,N!==t?(Oe=m,Q=cn(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ul?(Q=Ul,b+=2):(Q=t,I===0&&be(Hs)),Q!==t?(N=b,U=b,ce=On(),ce!==t?(Se=On(),Se!==t?(ht=On(),ht!==t?(Bt=On(),Bt!==t?(ce=[ce,Se,ht,Bt],U=ce):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t),U!==t?N=r.substring(N,b):N=U,N!==t?(Oe=m,Q=cn(N),m=Q):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Hl?(Q=Hl,b+=2):(Q=t,I===0&&be(yA)),Q!==t?(N=b,U=b,ce=On(),ce!==t?(Se=On(),Se!==t?(ht=On(),ht!==t?(Bt=On(),Bt!==t?(qr=On(),qr!==t?(hi=On(),hi!==t?(as=On(),as!==t?(AS=On(),AS!==t?(ce=[ce,Se,ht,Bt,qr,hi,as,AS],U=ce):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t)):(b=U,U=t),U!==t?N=r.substring(N,b):N=U,N!==t?(Oe=m,Q=Cg(N),m=Q):(b=m,m=t)):(b=m,m=t)))),m}function nS(){var m;return mg.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(Ca)),m}function On(){var m;return ma.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(rt)),m}function vge(){var m,Q,N,U,ce;if(m=b,Q=[],N=b,r.charCodeAt(b)===92?(U=ss,b++):(U=t,I===0&&be(gt)),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t),N===t&&(N=b,U=b,I++,ce=iK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t)),N!==t)for(;N!==t;)Q.push(N),N=b,r.charCodeAt(b)===92?(U=ss,b++):(U=t,I===0&&be(gt)),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t),N===t&&(N=b,U=b,I++,ce=iK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t));else Q=t;return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function sS(){var m,Q,N,U,ce,Se;if(m=b,r.charCodeAt(b)===45?(Q=wA,b++):(Q=t,I===0&&be(Gl)),Q===t&&(r.charCodeAt(b)===43?(Q=Gs,b++):(Q=t,I===0&&be(Yl))),Q===t&&(Q=null),Q!==t){if(N=[],qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne)),U!==t)for(;U!==t;)N.push(U),qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne));else N=t;if(N!==t)if(r.charCodeAt(b)===46?(U=KE,b++):(U=t,I===0&&be(Rp)),U!==t){if(ce=[],qe.test(r.charAt(b))?(Se=r.charAt(b),b++):(Se=t,I===0&&be(ne)),Se!==t)for(;Se!==t;)ce.push(Se),qe.test(r.charAt(b))?(Se=r.charAt(b),b++):(Se=t,I===0&&be(ne));else ce=t;ce!==t?(Oe=m,Q=Eg(Q,N,ce),m=Q):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;if(m===t){if(m=b,r.charCodeAt(b)===45?(Q=wA,b++):(Q=t,I===0&&be(Gl)),Q===t&&(r.charCodeAt(b)===43?(Q=Gs,b++):(Q=t,I===0&&be(Yl))),Q===t&&(Q=null),Q!==t){if(N=[],qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne)),U!==t)for(;U!==t;)N.push(U),qe.test(r.charAt(b))?(U=r.charAt(b),b++):(U=t,I===0&&be(ne));else N=t;N!==t?(Oe=m,Q=Fp(Q,N),m=Q):(b=m,m=t)}else b=m,m=t;if(m===t&&(m=b,Q=aS(),Q!==t&&(Oe=m,Q=UE(Q)),m=Q,m===t&&(m=b,Q=ql(),Q!==t&&(Oe=m,Q=jl(Q)),m=Q,m===t)))if(m=b,r.charCodeAt(b)===40?(Q=ge,b++):(Q=t,I===0&&be(re)),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();if(N!==t)if(U=$1(),U!==t){for(ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();ce!==t?(r.charCodeAt(b)===41?(Se=M,b++):(Se=t,I===0&&be(F)),Se!==t?(Oe=m,Q=HE(U),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t}return m}function oS(){var m,Q,N,U,ce,Se,ht,Bt;if(m=b,Q=sS(),Q!==t){for(N=[],U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===42?(Se=Ig,b++):(Se=t,I===0&&be(BA)),Se===t&&(r.charCodeAt(b)===47?(Se=Rr,b++):(Se=t,I===0&&be(GE))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=sS(),Bt!==t?(Oe=U,ce=Ys(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t;for(;U!==t;){for(N.push(U),U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===42?(Se=Ig,b++):(Se=t,I===0&&be(BA)),Se===t&&(r.charCodeAt(b)===47?(Se=Rr,b++):(Se=t,I===0&&be(GE))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=sS(),Bt!==t?(Oe=U,ce=Ys(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t}N!==t?(Oe=m,Q=js(Q,N),m=Q):(b=m,m=t)}else b=m,m=t;return m}function $1(){var m,Q,N,U,ce,Se,ht,Bt;if(m=b,Q=oS(),Q!==t){for(N=[],U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===43?(Se=Gs,b++):(Se=t,I===0&&be(Yl)),Se===t&&(r.charCodeAt(b)===45?(Se=wA,b++):(Se=t,I===0&&be(Gl))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=oS(),Bt!==t?(Oe=U,ce=yg(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t;for(;U!==t;){for(N.push(U),U=b,ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();if(ce!==t)if(r.charCodeAt(b)===43?(Se=Gs,b++):(Se=t,I===0&&be(Yl)),Se===t&&(r.charCodeAt(b)===45?(Se=wA,b++):(Se=t,I===0&&be(Gl))),Se!==t){for(ht=[],Bt=He();Bt!==t;)ht.push(Bt),Bt=He();ht!==t?(Bt=oS(),Bt!==t?(Oe=U,ce=yg(Q,Se,Bt),U=ce):(b=U,U=t)):(b=U,U=t)}else b=U,U=t;else b=U,U=t}N!==t?(Oe=m,Q=js(Q,N),m=Q):(b=m,m=t)}else b=m,m=t;return m}function eK(){var m,Q,N,U,ce,Se;if(m=b,r.substr(b,3)===bA?(Q=bA,b+=3):(Q=t,I===0&&be(R)),Q!==t){for(N=[],U=He();U!==t;)N.push(U),U=He();if(N!==t)if(U=$1(),U!==t){for(ce=[],Se=He();Se!==t;)ce.push(Se),Se=He();ce!==t?(r.substr(b,2)===q?(Se=q,b+=2):(Se=t,I===0&&be(Ce)),Se!==t?(Oe=m,Q=Ke(U),m=Q):(b=m,m=t)):(b=m,m=t)}else b=m,m=t;else b=m,m=t}else b=m,m=t;return m}function tK(){var m,Q,N,U;return m=b,r.substr(b,2)===Re?(Q=Re,b+=2):(Q=t,I===0&&be(ze)),Q!==t?(N=Or(),N!==t?(r.charCodeAt(b)===41?(U=M,b++):(U=t,I===0&&be(F)),U!==t?(Oe=m,Q=dt(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m}function aS(){var m,Q,N,U,ce,Se;return m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,2)===JQ?(U=JQ,b+=2):(U=t,I===0&&be(k1)),U!==t?(ce=q1(),ce!==t?(r.charCodeAt(b)===125?(Se=Fe,b++):(Se=t,I===0&&be(Ne)),Se!==t?(Oe=m,Q=R1(N,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,3)===WQ?(U=WQ,b+=3):(U=t,I===0&&be(F1)),U!==t?(Oe=m,Q=N1(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,2)===zQ?(U=zQ,b+=2):(U=t,I===0&&be(T1)),U!==t?(ce=q1(),ce!==t?(r.charCodeAt(b)===125?(Se=Fe,b++):(Se=t,I===0&&be(Ne)),Se!==t?(Oe=m,Q=L1(N,ce),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.substr(b,3)===VQ?(U=VQ,b+=3):(U=t,I===0&&be(M1)),U!==t?(Oe=m,Q=O1(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.substr(b,2)===Ft?(Q=Ft,b+=2):(Q=t,I===0&&be(Ln)),Q!==t?(N=ql(),N!==t?(r.charCodeAt(b)===125?(U=Fe,b++):(U=t,I===0&&be(Ne)),U!==t?(Oe=m,Q=XQ(N),m=Q):(b=m,m=t)):(b=m,m=t)):(b=m,m=t),m===t&&(m=b,r.charCodeAt(b)===36?(Q=K1,b++):(Q=t,I===0&&be(U1)),Q!==t?(N=ql(),N!==t?(Oe=m,Q=XQ(N),m=Q):(b=m,m=t)):(b=m,m=t)))))),m}function xge(){var m,Q,N;return m=b,Q=Pge(),Q!==t?(Oe=b,N=H1(Q),N?N=void 0:N=t,N!==t?(Oe=m,Q=G1(Q),m=Q):(b=m,m=t)):(b=m,m=t),m}function Pge(){var m,Q,N,U,ce;if(m=b,Q=[],N=b,U=b,I++,ce=nK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t),N!==t)for(;N!==t;)Q.push(N),N=b,U=b,I++,ce=nK(),I--,ce===t?U=void 0:(b=U,U=t),U!==t?(r.length>b?(ce=r.charAt(b),b++):(ce=t,I===0&&be(bo)),ce!==t?(Oe=N,U=ln(ce),N=U):(b=N,N=t)):(b=N,N=t);else Q=t;return Q!==t&&(Oe=m,Q=Fn(Q)),m=Q,m}function rK(){var m,Q,N;if(m=b,Q=[],ZQ.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(_Q)),N!==t)for(;N!==t;)Q.push(N),ZQ.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(_Q));else Q=t;return Q!==t&&(Oe=m,Q=$Q()),m=Q,m}function ql(){var m,Q,N;if(m=b,Q=[],eS.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(tS)),N!==t)for(;N!==t;)Q.push(N),eS.test(r.charAt(b))?(N=r.charAt(b),b++):(N=t,I===0&&be(tS));else Q=t;return Q!==t&&(Oe=m,Q=$Q()),m=Q,m}function iK(){var m;return Y1.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(wg)),m}function nK(){var m;return rS.test(r.charAt(b))?(m=r.charAt(b),b++):(m=t,I===0&&be(iS)),m}function He(){var m,Q;if(m=[],YE.test(r.charAt(b))?(Q=r.charAt(b),b++):(Q=t,I===0&&be(jE)),Q!==t)for(;Q!==t;)m.push(Q),YE.test(r.charAt(b))?(Q=r.charAt(b),b++):(Q=t,I===0&&be(jE));else m=t;return m}if(k=n(),k!==t&&b===r.length)return k;throw k!==t&&b{"use strict";function Dfe(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function $l(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,$l)}Dfe($l,Error);$l.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,f=1;gH&&(H=v,j=[]),j.push(ne))}function Ne(ne,Y){return new $l(ne,null,null,Y)}function oe(ne,Y,he){return new $l($l.buildMessage(ne,Y),ne,Y,he)}function le(){var ne,Y,he,ie;return ne=v,Y=Be(),Y!==t?(r.charCodeAt(v)===47?(he=s,v++):(he=t,$===0&&Fe(o)),he!==t?(ie=Be(),ie!==t?(D=ne,Y=a(Y,ie),ne=Y):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t),ne===t&&(ne=v,Y=Be(),Y!==t&&(D=ne,Y=l(Y)),ne=Y),ne}function Be(){var ne,Y,he,ie;return ne=v,Y=fe(),Y!==t?(r.charCodeAt(v)===64?(he=c,v++):(he=t,$===0&&Fe(u)),he!==t?(ie=qe(),ie!==t?(D=ne,Y=g(Y,ie),ne=Y):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t),ne===t&&(ne=v,Y=fe(),Y!==t&&(D=ne,Y=f(Y)),ne=Y),ne}function fe(){var ne,Y,he,ie,de;return ne=v,r.charCodeAt(v)===64?(Y=c,v++):(Y=t,$===0&&Fe(u)),Y!==t?(he=ae(),he!==t?(r.charCodeAt(v)===47?(ie=s,v++):(ie=t,$===0&&Fe(o)),ie!==t?(de=ae(),de!==t?(D=ne,Y=h(),ne=Y):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t)):(v=ne,ne=t),ne===t&&(ne=v,Y=ae(),Y!==t&&(D=ne,Y=h()),ne=Y),ne}function ae(){var ne,Y,he;if(ne=v,Y=[],p.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(C)),he!==t)for(;he!==t;)Y.push(he),p.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(C));else Y=t;return Y!==t&&(D=ne,Y=h()),ne=Y,ne}function qe(){var ne,Y,he;if(ne=v,Y=[],y.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(B)),he!==t)for(;he!==t;)Y.push(he),y.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Fe(B));else Y=t;return Y!==t&&(D=ne,Y=h()),ne=Y,ne}if(V=n(),V!==t&&v===r.length)return V;throw V!==t&&v{"use strict";function mU(r){return typeof r>"u"||r===null}function Rfe(r){return typeof r=="object"&&r!==null}function Ffe(r){return Array.isArray(r)?r:mU(r)?[]:[r]}function Nfe(r,e){var t,i,n,s;if(e)for(s=Object.keys(e),t=0,i=s.length;t{"use strict";function Vp(r,e){Error.call(this),this.name="YAMLException",this.reason=r,this.mark=e,this.message=(this.reason||"(unknown reason)")+(this.mark?" "+this.mark.toString():""),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||""}Vp.prototype=Object.create(Error.prototype);Vp.prototype.constructor=Vp;Vp.prototype.toString=function(e){var t=this.name+": ";return t+=this.reason||"(unknown reason)",!e&&this.mark&&(t+=" "+this.mark.toString()),t};EU.exports=Vp});var wU=w((SZe,yU)=>{"use strict";var IU=tc();function HS(r,e,t,i,n){this.name=r,this.buffer=e,this.position=t,this.line=i,this.column=n}HS.prototype.getSnippet=function(e,t){var i,n,s,o,a;if(!this.buffer)return null;for(e=e||4,t=t||75,i="",n=this.position;n>0&&`\0\r +\x85\u2028\u2029`.indexOf(this.buffer.charAt(n-1))===-1;)if(n-=1,this.position-n>t/2-1){i=" ... ",n+=5;break}for(s="",o=this.position;ot/2-1){s=" ... ",o-=5;break}return a=this.buffer.slice(n,o),IU.repeat(" ",e)+i+a+s+` +`+IU.repeat(" ",e+this.position-n+i.length)+"^"};HS.prototype.toString=function(e){var t,i="";return this.name&&(i+='in "'+this.name+'" '),i+="at line "+(this.line+1)+", column "+(this.column+1),e||(t=this.getSnippet(),t&&(i+=`: +`+t)),i};yU.exports=HS});var si=w((vZe,bU)=>{"use strict";var BU=Ng(),Mfe=["kind","resolve","construct","instanceOf","predicate","represent","defaultStyle","styleAliases"],Ofe=["scalar","sequence","mapping"];function Kfe(r){var e={};return r!==null&&Object.keys(r).forEach(function(t){r[t].forEach(function(i){e[String(i)]=t})}),e}function Ufe(r,e){if(e=e||{},Object.keys(e).forEach(function(t){if(Mfe.indexOf(t)===-1)throw new BU('Unknown option "'+t+'" is met in definition of "'+r+'" YAML type.')}),this.tag=r,this.kind=e.kind||null,this.resolve=e.resolve||function(){return!0},this.construct=e.construct||function(t){return t},this.instanceOf=e.instanceOf||null,this.predicate=e.predicate||null,this.represent=e.represent||null,this.defaultStyle=e.defaultStyle||null,this.styleAliases=Kfe(e.styleAliases||null),Ofe.indexOf(this.kind)===-1)throw new BU('Unknown kind "'+this.kind+'" is specified for "'+r+'" YAML type.')}bU.exports=Ufe});var rc=w((xZe,SU)=>{"use strict";var QU=tc(),dI=Ng(),Hfe=si();function GS(r,e,t){var i=[];return r.include.forEach(function(n){t=GS(n,e,t)}),r[e].forEach(function(n){t.forEach(function(s,o){s.tag===n.tag&&s.kind===n.kind&&i.push(o)}),t.push(n)}),t.filter(function(n,s){return i.indexOf(s)===-1})}function Gfe(){var r={scalar:{},sequence:{},mapping:{},fallback:{}},e,t;function i(n){r[n.kind][n.tag]=r.fallback[n.tag]=n}for(e=0,t=arguments.length;e{"use strict";var Yfe=si();vU.exports=new Yfe("tag:yaml.org,2002:str",{kind:"scalar",construct:function(r){return r!==null?r:""}})});var DU=w((DZe,PU)=>{"use strict";var jfe=si();PU.exports=new jfe("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(r){return r!==null?r:[]}})});var RU=w((kZe,kU)=>{"use strict";var qfe=si();kU.exports=new qfe("tag:yaml.org,2002:map",{kind:"mapping",construct:function(r){return r!==null?r:{}}})});var CI=w((RZe,FU)=>{"use strict";var Jfe=rc();FU.exports=new Jfe({explicit:[xU(),DU(),RU()]})});var TU=w((FZe,NU)=>{"use strict";var Wfe=si();function zfe(r){if(r===null)return!0;var e=r.length;return e===1&&r==="~"||e===4&&(r==="null"||r==="Null"||r==="NULL")}function Vfe(){return null}function Xfe(r){return r===null}NU.exports=new Wfe("tag:yaml.org,2002:null",{kind:"scalar",resolve:zfe,construct:Vfe,predicate:Xfe,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"}},defaultStyle:"lowercase"})});var MU=w((NZe,LU)=>{"use strict";var Zfe=si();function _fe(r){if(r===null)return!1;var e=r.length;return e===4&&(r==="true"||r==="True"||r==="TRUE")||e===5&&(r==="false"||r==="False"||r==="FALSE")}function $fe(r){return r==="true"||r==="True"||r==="TRUE"}function ehe(r){return Object.prototype.toString.call(r)==="[object Boolean]"}LU.exports=new Zfe("tag:yaml.org,2002:bool",{kind:"scalar",resolve:_fe,construct:$fe,predicate:ehe,represent:{lowercase:function(r){return r?"true":"false"},uppercase:function(r){return r?"TRUE":"FALSE"},camelcase:function(r){return r?"True":"False"}},defaultStyle:"lowercase"})});var KU=w((TZe,OU)=>{"use strict";var the=tc(),rhe=si();function ihe(r){return 48<=r&&r<=57||65<=r&&r<=70||97<=r&&r<=102}function nhe(r){return 48<=r&&r<=55}function she(r){return 48<=r&&r<=57}function ohe(r){if(r===null)return!1;var e=r.length,t=0,i=!1,n;if(!e)return!1;if(n=r[t],(n==="-"||n==="+")&&(n=r[++t]),n==="0"){if(t+1===e)return!0;if(n=r[++t],n==="b"){for(t++;t=0?"0b"+r.toString(2):"-0b"+r.toString(2).slice(1)},octal:function(r){return r>=0?"0"+r.toString(8):"-0"+r.toString(8).slice(1)},decimal:function(r){return r.toString(10)},hexadecimal:function(r){return r>=0?"0x"+r.toString(16).toUpperCase():"-0x"+r.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}})});var GU=w((LZe,HU)=>{"use strict";var UU=tc(),lhe=si(),che=new RegExp("^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function uhe(r){return!(r===null||!che.test(r)||r[r.length-1]==="_")}function ghe(r){var e,t,i,n;return e=r.replace(/_/g,"").toLowerCase(),t=e[0]==="-"?-1:1,n=[],"+-".indexOf(e[0])>=0&&(e=e.slice(1)),e===".inf"?t===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:e===".nan"?NaN:e.indexOf(":")>=0?(e.split(":").forEach(function(s){n.unshift(parseFloat(s,10))}),e=0,i=1,n.forEach(function(s){e+=s*i,i*=60}),t*e):t*parseFloat(e,10)}var fhe=/^[-+]?[0-9]+e/;function hhe(r,e){var t;if(isNaN(r))switch(e){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===r)switch(e){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===r)switch(e){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(UU.isNegativeZero(r))return"-0.0";return t=r.toString(10),fhe.test(t)?t.replace("e",".e"):t}function phe(r){return Object.prototype.toString.call(r)==="[object Number]"&&(r%1!==0||UU.isNegativeZero(r))}HU.exports=new lhe("tag:yaml.org,2002:float",{kind:"scalar",resolve:uhe,construct:ghe,predicate:phe,represent:hhe,defaultStyle:"lowercase"})});var YS=w((MZe,YU)=>{"use strict";var dhe=rc();YU.exports=new dhe({include:[CI()],implicit:[TU(),MU(),KU(),GU()]})});var jS=w((OZe,jU)=>{"use strict";var Che=rc();jU.exports=new Che({include:[YS()]})});var zU=w((KZe,WU)=>{"use strict";var mhe=si(),qU=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),JU=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function Ehe(r){return r===null?!1:qU.exec(r)!==null||JU.exec(r)!==null}function Ihe(r){var e,t,i,n,s,o,a,l=0,c=null,u,g,f;if(e=qU.exec(r),e===null&&(e=JU.exec(r)),e===null)throw new Error("Date resolve error");if(t=+e[1],i=+e[2]-1,n=+e[3],!e[4])return new Date(Date.UTC(t,i,n));if(s=+e[4],o=+e[5],a=+e[6],e[7]){for(l=e[7].slice(0,3);l.length<3;)l+="0";l=+l}return e[9]&&(u=+e[10],g=+(e[11]||0),c=(u*60+g)*6e4,e[9]==="-"&&(c=-c)),f=new Date(Date.UTC(t,i,n,s,o,a,l)),c&&f.setTime(f.getTime()-c),f}function yhe(r){return r.toISOString()}WU.exports=new mhe("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:Ehe,construct:Ihe,instanceOf:Date,represent:yhe})});var XU=w((UZe,VU)=>{"use strict";var whe=si();function Bhe(r){return r==="<<"||r===null}VU.exports=new whe("tag:yaml.org,2002:merge",{kind:"scalar",resolve:Bhe})});var $U=w((HZe,_U)=>{"use strict";var ic;try{ZU=J,ic=ZU("buffer").Buffer}catch{}var ZU,bhe=si(),qS=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= +\r`;function Qhe(r){if(r===null)return!1;var e,t,i=0,n=r.length,s=qS;for(t=0;t64)){if(e<0)return!1;i+=6}return i%8===0}function She(r){var e,t,i=r.replace(/[\r\n=]/g,""),n=i.length,s=qS,o=0,a=[];for(e=0;e>16&255),a.push(o>>8&255),a.push(o&255)),o=o<<6|s.indexOf(i.charAt(e));return t=n%4*6,t===0?(a.push(o>>16&255),a.push(o>>8&255),a.push(o&255)):t===18?(a.push(o>>10&255),a.push(o>>2&255)):t===12&&a.push(o>>4&255),ic?ic.from?ic.from(a):new ic(a):a}function vhe(r){var e="",t=0,i,n,s=r.length,o=qS;for(i=0;i>18&63],e+=o[t>>12&63],e+=o[t>>6&63],e+=o[t&63]),t=(t<<8)+r[i];return n=s%3,n===0?(e+=o[t>>18&63],e+=o[t>>12&63],e+=o[t>>6&63],e+=o[t&63]):n===2?(e+=o[t>>10&63],e+=o[t>>4&63],e+=o[t<<2&63],e+=o[64]):n===1&&(e+=o[t>>2&63],e+=o[t<<4&63],e+=o[64],e+=o[64]),e}function xhe(r){return ic&&ic.isBuffer(r)}_U.exports=new bhe("tag:yaml.org,2002:binary",{kind:"scalar",resolve:Qhe,construct:She,predicate:xhe,represent:vhe})});var t2=w((YZe,e2)=>{"use strict";var Phe=si(),Dhe=Object.prototype.hasOwnProperty,khe=Object.prototype.toString;function Rhe(r){if(r===null)return!0;var e=[],t,i,n,s,o,a=r;for(t=0,i=a.length;t{"use strict";var Nhe=si(),The=Object.prototype.toString;function Lhe(r){if(r===null)return!0;var e,t,i,n,s,o=r;for(s=new Array(o.length),e=0,t=o.length;e{"use strict";var Ohe=si(),Khe=Object.prototype.hasOwnProperty;function Uhe(r){if(r===null)return!0;var e,t=r;for(e in t)if(Khe.call(t,e)&&t[e]!==null)return!1;return!0}function Hhe(r){return r!==null?r:{}}n2.exports=new Ohe("tag:yaml.org,2002:set",{kind:"mapping",resolve:Uhe,construct:Hhe})});var Lg=w((JZe,o2)=>{"use strict";var Ghe=rc();o2.exports=new Ghe({include:[jS()],implicit:[zU(),XU()],explicit:[$U(),t2(),i2(),s2()]})});var A2=w((WZe,a2)=>{"use strict";var Yhe=si();function jhe(){return!0}function qhe(){}function Jhe(){return""}function Whe(r){return typeof r>"u"}a2.exports=new Yhe("tag:yaml.org,2002:js/undefined",{kind:"scalar",resolve:jhe,construct:qhe,predicate:Whe,represent:Jhe})});var c2=w((zZe,l2)=>{"use strict";var zhe=si();function Vhe(r){if(r===null||r.length===0)return!1;var e=r,t=/\/([gim]*)$/.exec(r),i="";return!(e[0]==="/"&&(t&&(i=t[1]),i.length>3||e[e.length-i.length-1]!=="/"))}function Xhe(r){var e=r,t=/\/([gim]*)$/.exec(r),i="";return e[0]==="/"&&(t&&(i=t[1]),e=e.slice(1,e.length-i.length-1)),new RegExp(e,i)}function Zhe(r){var e="/"+r.source+"/";return r.global&&(e+="g"),r.multiline&&(e+="m"),r.ignoreCase&&(e+="i"),e}function _he(r){return Object.prototype.toString.call(r)==="[object RegExp]"}l2.exports=new zhe("tag:yaml.org,2002:js/regexp",{kind:"scalar",resolve:Vhe,construct:Xhe,predicate:_he,represent:Zhe})});var f2=w((VZe,g2)=>{"use strict";var mI;try{u2=J,mI=u2("esprima")}catch{typeof window<"u"&&(mI=window.esprima)}var u2,$he=si();function epe(r){if(r===null)return!1;try{var e="("+r+")",t=mI.parse(e,{range:!0});return!(t.type!=="Program"||t.body.length!==1||t.body[0].type!=="ExpressionStatement"||t.body[0].expression.type!=="ArrowFunctionExpression"&&t.body[0].expression.type!=="FunctionExpression")}catch{return!1}}function tpe(r){var e="("+r+")",t=mI.parse(e,{range:!0}),i=[],n;if(t.type!=="Program"||t.body.length!==1||t.body[0].type!=="ExpressionStatement"||t.body[0].expression.type!=="ArrowFunctionExpression"&&t.body[0].expression.type!=="FunctionExpression")throw new Error("Failed to resolve function");return t.body[0].expression.params.forEach(function(s){i.push(s.name)}),n=t.body[0].expression.body.range,t.body[0].expression.body.type==="BlockStatement"?new Function(i,e.slice(n[0]+1,n[1]-1)):new Function(i,"return "+e.slice(n[0],n[1]))}function rpe(r){return r.toString()}function ipe(r){return Object.prototype.toString.call(r)==="[object Function]"}g2.exports=new $he("tag:yaml.org,2002:js/function",{kind:"scalar",resolve:epe,construct:tpe,predicate:ipe,represent:rpe})});var Xp=w((ZZe,p2)=>{"use strict";var h2=rc();p2.exports=h2.DEFAULT=new h2({include:[Lg()],explicit:[A2(),c2(),f2()]})});var N2=w((_Ze,Zp)=>{"use strict";var Ba=tc(),w2=Ng(),npe=wU(),B2=Lg(),spe=Xp(),kA=Object.prototype.hasOwnProperty,EI=1,b2=2,Q2=3,II=4,JS=1,ope=2,d2=3,ape=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,Ape=/[\x85\u2028\u2029]/,lpe=/[,\[\]\{\}]/,S2=/^(?:!|!!|![a-z\-]+!)$/i,v2=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function C2(r){return Object.prototype.toString.call(r)}function xo(r){return r===10||r===13}function sc(r){return r===9||r===32}function fn(r){return r===9||r===32||r===10||r===13}function Mg(r){return r===44||r===91||r===93||r===123||r===125}function cpe(r){var e;return 48<=r&&r<=57?r-48:(e=r|32,97<=e&&e<=102?e-97+10:-1)}function upe(r){return r===120?2:r===117?4:r===85?8:0}function gpe(r){return 48<=r&&r<=57?r-48:-1}function m2(r){return r===48?"\0":r===97?"\x07":r===98?"\b":r===116||r===9?" ":r===110?` +`:r===118?"\v":r===102?"\f":r===114?"\r":r===101?"\x1B":r===32?" ":r===34?'"':r===47?"/":r===92?"\\":r===78?"\x85":r===95?"\xA0":r===76?"\u2028":r===80?"\u2029":""}function fpe(r){return r<=65535?String.fromCharCode(r):String.fromCharCode((r-65536>>10)+55296,(r-65536&1023)+56320)}var x2=new Array(256),P2=new Array(256);for(nc=0;nc<256;nc++)x2[nc]=m2(nc)?1:0,P2[nc]=m2(nc);var nc;function hpe(r,e){this.input=r,this.filename=e.filename||null,this.schema=e.schema||spe,this.onWarning=e.onWarning||null,this.legacy=e.legacy||!1,this.json=e.json||!1,this.listener=e.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=r.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.documents=[]}function D2(r,e){return new w2(e,new npe(r.filename,r.input,r.position,r.line,r.position-r.lineStart))}function ft(r,e){throw D2(r,e)}function yI(r,e){r.onWarning&&r.onWarning.call(null,D2(r,e))}var E2={YAML:function(e,t,i){var n,s,o;e.version!==null&&ft(e,"duplication of %YAML directive"),i.length!==1&&ft(e,"YAML directive accepts exactly one argument"),n=/^([0-9]+)\.([0-9]+)$/.exec(i[0]),n===null&&ft(e,"ill-formed argument of the YAML directive"),s=parseInt(n[1],10),o=parseInt(n[2],10),s!==1&&ft(e,"unacceptable YAML version of the document"),e.version=i[0],e.checkLineBreaks=o<2,o!==1&&o!==2&&yI(e,"unsupported YAML version of the document")},TAG:function(e,t,i){var n,s;i.length!==2&&ft(e,"TAG directive accepts exactly two arguments"),n=i[0],s=i[1],S2.test(n)||ft(e,"ill-formed tag handle (first argument) of the TAG directive"),kA.call(e.tagMap,n)&&ft(e,'there is a previously declared suffix for "'+n+'" tag handle'),v2.test(s)||ft(e,"ill-formed tag prefix (second argument) of the TAG directive"),e.tagMap[n]=s}};function DA(r,e,t,i){var n,s,o,a;if(e1&&(r.result+=Ba.repeat(` +`,e-1))}function ppe(r,e,t){var i,n,s,o,a,l,c,u,g=r.kind,f=r.result,h;if(h=r.input.charCodeAt(r.position),fn(h)||Mg(h)||h===35||h===38||h===42||h===33||h===124||h===62||h===39||h===34||h===37||h===64||h===96||(h===63||h===45)&&(n=r.input.charCodeAt(r.position+1),fn(n)||t&&Mg(n)))return!1;for(r.kind="scalar",r.result="",s=o=r.position,a=!1;h!==0;){if(h===58){if(n=r.input.charCodeAt(r.position+1),fn(n)||t&&Mg(n))break}else if(h===35){if(i=r.input.charCodeAt(r.position-1),fn(i))break}else{if(r.position===r.lineStart&&wI(r)||t&&Mg(h))break;if(xo(h))if(l=r.line,c=r.lineStart,u=r.lineIndent,zr(r,!1,-1),r.lineIndent>=e){a=!0,h=r.input.charCodeAt(r.position);continue}else{r.position=o,r.line=l,r.lineStart=c,r.lineIndent=u;break}}a&&(DA(r,s,o,!1),zS(r,r.line-l),s=o=r.position,a=!1),sc(h)||(o=r.position+1),h=r.input.charCodeAt(++r.position)}return DA(r,s,o,!1),r.result?!0:(r.kind=g,r.result=f,!1)}function dpe(r,e){var t,i,n;if(t=r.input.charCodeAt(r.position),t!==39)return!1;for(r.kind="scalar",r.result="",r.position++,i=n=r.position;(t=r.input.charCodeAt(r.position))!==0;)if(t===39)if(DA(r,i,r.position,!0),t=r.input.charCodeAt(++r.position),t===39)i=r.position,r.position++,n=r.position;else return!0;else xo(t)?(DA(r,i,n,!0),zS(r,zr(r,!1,e)),i=n=r.position):r.position===r.lineStart&&wI(r)?ft(r,"unexpected end of the document within a single quoted scalar"):(r.position++,n=r.position);ft(r,"unexpected end of the stream within a single quoted scalar")}function Cpe(r,e){var t,i,n,s,o,a;if(a=r.input.charCodeAt(r.position),a!==34)return!1;for(r.kind="scalar",r.result="",r.position++,t=i=r.position;(a=r.input.charCodeAt(r.position))!==0;){if(a===34)return DA(r,t,r.position,!0),r.position++,!0;if(a===92){if(DA(r,t,r.position,!0),a=r.input.charCodeAt(++r.position),xo(a))zr(r,!1,e);else if(a<256&&x2[a])r.result+=P2[a],r.position++;else if((o=upe(a))>0){for(n=o,s=0;n>0;n--)a=r.input.charCodeAt(++r.position),(o=cpe(a))>=0?s=(s<<4)+o:ft(r,"expected hexadecimal character");r.result+=fpe(s),r.position++}else ft(r,"unknown escape sequence");t=i=r.position}else xo(a)?(DA(r,t,i,!0),zS(r,zr(r,!1,e)),t=i=r.position):r.position===r.lineStart&&wI(r)?ft(r,"unexpected end of the document within a double quoted scalar"):(r.position++,i=r.position)}ft(r,"unexpected end of the stream within a double quoted scalar")}function mpe(r,e){var t=!0,i,n=r.tag,s,o=r.anchor,a,l,c,u,g,f={},h,p,C,y;if(y=r.input.charCodeAt(r.position),y===91)l=93,g=!1,s=[];else if(y===123)l=125,g=!0,s={};else return!1;for(r.anchor!==null&&(r.anchorMap[r.anchor]=s),y=r.input.charCodeAt(++r.position);y!==0;){if(zr(r,!0,e),y=r.input.charCodeAt(r.position),y===l)return r.position++,r.tag=n,r.anchor=o,r.kind=g?"mapping":"sequence",r.result=s,!0;t||ft(r,"missed comma between flow collection entries"),p=h=C=null,c=u=!1,y===63&&(a=r.input.charCodeAt(r.position+1),fn(a)&&(c=u=!0,r.position++,zr(r,!0,e))),i=r.line,Kg(r,e,EI,!1,!0),p=r.tag,h=r.result,zr(r,!0,e),y=r.input.charCodeAt(r.position),(u||r.line===i)&&y===58&&(c=!0,y=r.input.charCodeAt(++r.position),zr(r,!0,e),Kg(r,e,EI,!1,!0),C=r.result),g?Og(r,s,f,p,h,C):c?s.push(Og(r,null,f,p,h,C)):s.push(h),zr(r,!0,e),y=r.input.charCodeAt(r.position),y===44?(t=!0,y=r.input.charCodeAt(++r.position)):t=!1}ft(r,"unexpected end of the stream within a flow collection")}function Epe(r,e){var t,i,n=JS,s=!1,o=!1,a=e,l=0,c=!1,u,g;if(g=r.input.charCodeAt(r.position),g===124)i=!1;else if(g===62)i=!0;else return!1;for(r.kind="scalar",r.result="";g!==0;)if(g=r.input.charCodeAt(++r.position),g===43||g===45)JS===n?n=g===43?d2:ope:ft(r,"repeat of a chomping mode identifier");else if((u=gpe(g))>=0)u===0?ft(r,"bad explicit indentation width of a block scalar; it cannot be less than one"):o?ft(r,"repeat of an indentation width identifier"):(a=e+u-1,o=!0);else break;if(sc(g)){do g=r.input.charCodeAt(++r.position);while(sc(g));if(g===35)do g=r.input.charCodeAt(++r.position);while(!xo(g)&&g!==0)}for(;g!==0;){for(WS(r),r.lineIndent=0,g=r.input.charCodeAt(r.position);(!o||r.lineIndenta&&(a=r.lineIndent),xo(g)){l++;continue}if(r.lineIndente)&&l!==0)ft(r,"bad indentation of a sequence entry");else if(r.lineIndente)&&(Kg(r,e,II,!0,n)&&(p?f=r.result:h=r.result),p||(Og(r,c,u,g,f,h,s,o),g=f=h=null),zr(r,!0,-1),y=r.input.charCodeAt(r.position)),r.lineIndent>e&&y!==0)ft(r,"bad indentation of a mapping entry");else if(r.lineIndente?l=1:r.lineIndent===e?l=0:r.lineIndente?l=1:r.lineIndent===e?l=0:r.lineIndent tag; it should be "scalar", not "'+r.kind+'"'),g=0,f=r.implicitTypes.length;g tag; it should be "'+h.kind+'", not "'+r.kind+'"'),h.resolve(r.result)?(r.result=h.construct(r.result),r.anchor!==null&&(r.anchorMap[r.anchor]=r.result)):ft(r,"cannot resolve a node with !<"+r.tag+"> explicit tag")):ft(r,"unknown tag !<"+r.tag+">");return r.listener!==null&&r.listener("close",r),r.tag!==null||r.anchor!==null||u}function bpe(r){var e=r.position,t,i,n,s=!1,o;for(r.version=null,r.checkLineBreaks=r.legacy,r.tagMap={},r.anchorMap={};(o=r.input.charCodeAt(r.position))!==0&&(zr(r,!0,-1),o=r.input.charCodeAt(r.position),!(r.lineIndent>0||o!==37));){for(s=!0,o=r.input.charCodeAt(++r.position),t=r.position;o!==0&&!fn(o);)o=r.input.charCodeAt(++r.position);for(i=r.input.slice(t,r.position),n=[],i.length<1&&ft(r,"directive name must not be less than one character in length");o!==0;){for(;sc(o);)o=r.input.charCodeAt(++r.position);if(o===35){do o=r.input.charCodeAt(++r.position);while(o!==0&&!xo(o));break}if(xo(o))break;for(t=r.position;o!==0&&!fn(o);)o=r.input.charCodeAt(++r.position);n.push(r.input.slice(t,r.position))}o!==0&&WS(r),kA.call(E2,i)?E2[i](r,i,n):yI(r,'unknown document directive "'+i+'"')}if(zr(r,!0,-1),r.lineIndent===0&&r.input.charCodeAt(r.position)===45&&r.input.charCodeAt(r.position+1)===45&&r.input.charCodeAt(r.position+2)===45?(r.position+=3,zr(r,!0,-1)):s&&ft(r,"directives end mark is expected"),Kg(r,r.lineIndent-1,II,!1,!0),zr(r,!0,-1),r.checkLineBreaks&&Ape.test(r.input.slice(e,r.position))&&yI(r,"non-ASCII line breaks are interpreted as content"),r.documents.push(r.result),r.position===r.lineStart&&wI(r)){r.input.charCodeAt(r.position)===46&&(r.position+=3,zr(r,!0,-1));return}if(r.position"u"&&(t=e,e=null);var i=k2(r,t);if(typeof e!="function")return i;for(var n=0,s=i.length;n"u"&&(t=e,e=null),R2(r,e,Ba.extend({schema:B2},t))}function Spe(r,e){return F2(r,Ba.extend({schema:B2},e))}Zp.exports.loadAll=R2;Zp.exports.load=F2;Zp.exports.safeLoadAll=Qpe;Zp.exports.safeLoad=Spe});var iH=w(($Ze,_S)=>{"use strict";var $p=tc(),ed=Ng(),vpe=Xp(),xpe=Lg(),G2=Object.prototype.toString,Y2=Object.prototype.hasOwnProperty,Ppe=9,_p=10,Dpe=13,kpe=32,Rpe=33,Fpe=34,j2=35,Npe=37,Tpe=38,Lpe=39,Mpe=42,q2=44,Ope=45,J2=58,Kpe=61,Upe=62,Hpe=63,Gpe=64,W2=91,z2=93,Ype=96,V2=123,jpe=124,X2=125,Ni={};Ni[0]="\\0";Ni[7]="\\a";Ni[8]="\\b";Ni[9]="\\t";Ni[10]="\\n";Ni[11]="\\v";Ni[12]="\\f";Ni[13]="\\r";Ni[27]="\\e";Ni[34]='\\"';Ni[92]="\\\\";Ni[133]="\\N";Ni[160]="\\_";Ni[8232]="\\L";Ni[8233]="\\P";var qpe=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"];function Jpe(r,e){var t,i,n,s,o,a,l;if(e===null)return{};for(t={},i=Object.keys(e),n=0,s=i.length;n0?r.charCodeAt(s-1):null,f=f&&M2(o,a)}else{for(s=0;si&&r[g+1]!==" ",g=s);else if(!Ug(o))return BI;a=s>0?r.charCodeAt(s-1):null,f=f&&M2(o,a)}c=c||u&&s-g-1>i&&r[g+1]!==" "}return!l&&!c?f&&!n(r)?_2:$2:t>9&&Z2(r)?BI:c?tH:eH}function _pe(r,e,t,i){r.dump=function(){if(e.length===0)return"''";if(!r.noCompatMode&&qpe.indexOf(e)!==-1)return"'"+e+"'";var n=r.indent*Math.max(1,t),s=r.lineWidth===-1?-1:Math.max(Math.min(r.lineWidth,40),r.lineWidth-n),o=i||r.flowLevel>-1&&t>=r.flowLevel;function a(l){return zpe(r,l)}switch(Zpe(e,o,r.indent,s,a)){case _2:return e;case $2:return"'"+e.replace(/'/g,"''")+"'";case eH:return"|"+O2(e,r.indent)+K2(L2(e,n));case tH:return">"+O2(e,r.indent)+K2(L2($pe(e,s),n));case BI:return'"'+ede(e,s)+'"';default:throw new ed("impossible error: invalid scalar style")}}()}function O2(r,e){var t=Z2(r)?String(e):"",i=r[r.length-1]===` +`,n=i&&(r[r.length-2]===` +`||r===` +`),s=n?"+":i?"":"-";return t+s+` +`}function K2(r){return r[r.length-1]===` +`?r.slice(0,-1):r}function $pe(r,e){for(var t=/(\n+)([^\n]*)/g,i=function(){var c=r.indexOf(` +`);return c=c!==-1?c:r.length,t.lastIndex=c,U2(r.slice(0,c),e)}(),n=r[0]===` +`||r[0]===" ",s,o;o=t.exec(r);){var a=o[1],l=o[2];s=l[0]===" ",i+=a+(!n&&!s&&l!==""?` +`:"")+U2(l,e),n=s}return i}function U2(r,e){if(r===""||r[0]===" ")return r;for(var t=/ [^ ]/g,i,n=0,s,o=0,a=0,l="";i=t.exec(r);)a=i.index,a-n>e&&(s=o>n?o:a,l+=` +`+r.slice(n,s),n=s+1),o=a;return l+=` +`,r.length-n>e&&o>n?l+=r.slice(n,o)+` +`+r.slice(o+1):l+=r.slice(n),l.slice(1)}function ede(r){for(var e="",t,i,n,s=0;s=55296&&t<=56319&&(i=r.charCodeAt(s+1),i>=56320&&i<=57343)){e+=T2((t-55296)*1024+i-56320+65536),s++;continue}n=Ni[t],e+=!n&&Ug(t)?r[s]:n||T2(t)}return e}function tde(r,e,t){var i="",n=r.tag,s,o;for(s=0,o=t.length;s1024&&(u+="? "),u+=r.dump+(r.condenseFlow?'"':"")+":"+(r.condenseFlow?"":" "),oc(r,e,c,!1,!1)&&(u+=r.dump,i+=u));r.tag=n,r.dump="{"+i+"}"}function nde(r,e,t,i){var n="",s=r.tag,o=Object.keys(t),a,l,c,u,g,f;if(r.sortKeys===!0)o.sort();else if(typeof r.sortKeys=="function")o.sort(r.sortKeys);else if(r.sortKeys)throw new ed("sortKeys must be a boolean or a function");for(a=0,l=o.length;a1024,g&&(r.dump&&_p===r.dump.charCodeAt(0)?f+="?":f+="? "),f+=r.dump,g&&(f+=VS(r,e)),oc(r,e+1,u,!0,g)&&(r.dump&&_p===r.dump.charCodeAt(0)?f+=":":f+=": ",f+=r.dump,n+=f));r.tag=s,r.dump=n||"{}"}function H2(r,e,t){var i,n,s,o,a,l;for(n=t?r.explicitTypes:r.implicitTypes,s=0,o=n.length;s tag resolver accepts not "'+l+'" style');r.dump=i}return!0}return!1}function oc(r,e,t,i,n,s){r.tag=null,r.dump=t,H2(r,t,!1)||H2(r,t,!0);var o=G2.call(r.dump);i&&(i=r.flowLevel<0||r.flowLevel>e);var a=o==="[object Object]"||o==="[object Array]",l,c;if(a&&(l=r.duplicates.indexOf(t),c=l!==-1),(r.tag!==null&&r.tag!=="?"||c||r.indent!==2&&e>0)&&(n=!1),c&&r.usedDuplicates[l])r.dump="*ref_"+l;else{if(a&&c&&!r.usedDuplicates[l]&&(r.usedDuplicates[l]=!0),o==="[object Object]")i&&Object.keys(r.dump).length!==0?(nde(r,e,r.dump,n),c&&(r.dump="&ref_"+l+r.dump)):(ide(r,e,r.dump),c&&(r.dump="&ref_"+l+" "+r.dump));else if(o==="[object Array]"){var u=r.noArrayIndent&&e>0?e-1:e;i&&r.dump.length!==0?(rde(r,u,r.dump,n),c&&(r.dump="&ref_"+l+r.dump)):(tde(r,u,r.dump),c&&(r.dump="&ref_"+l+" "+r.dump))}else if(o==="[object String]")r.tag!=="?"&&_pe(r,r.dump,e,s);else{if(r.skipInvalid)return!1;throw new ed("unacceptable kind of an object to dump "+o)}r.tag!==null&&r.tag!=="?"&&(r.dump="!<"+r.tag+"> "+r.dump)}return!0}function sde(r,e){var t=[],i=[],n,s;for(XS(r,t,i),n=0,s=i.length;n{"use strict";var bI=N2(),nH=iH();function QI(r){return function(){throw new Error("Function "+r+" is deprecated and cannot be used.")}}Fr.exports.Type=si();Fr.exports.Schema=rc();Fr.exports.FAILSAFE_SCHEMA=CI();Fr.exports.JSON_SCHEMA=YS();Fr.exports.CORE_SCHEMA=jS();Fr.exports.DEFAULT_SAFE_SCHEMA=Lg();Fr.exports.DEFAULT_FULL_SCHEMA=Xp();Fr.exports.load=bI.load;Fr.exports.loadAll=bI.loadAll;Fr.exports.safeLoad=bI.safeLoad;Fr.exports.safeLoadAll=bI.safeLoadAll;Fr.exports.dump=nH.dump;Fr.exports.safeDump=nH.safeDump;Fr.exports.YAMLException=Ng();Fr.exports.MINIMAL_SCHEMA=CI();Fr.exports.SAFE_SCHEMA=Lg();Fr.exports.DEFAULT_SCHEMA=Xp();Fr.exports.scan=QI("scan");Fr.exports.parse=QI("parse");Fr.exports.compose=QI("compose");Fr.exports.addConstructor=QI("addConstructor")});var aH=w((t_e,oH)=>{"use strict";var ade=sH();oH.exports=ade});var lH=w((r_e,AH)=>{"use strict";function Ade(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function ac(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,ac)}Ade(ac,Error);ac.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,f=1;g({[Ke]:Ce})))},H=function(R){return R},j=function(R){return R},$=Us("correct indentation"),V=" ",W=ar(" ",!1),_=function(R){return R.length===bA*yg},A=function(R){return R.length===(bA+1)*yg},Ae=function(){return bA++,!0},ge=function(){return bA--,!0},re=function(){return pg()},M=Us("pseudostring"),F=/^[^\r\n\t ?:,\][{}#&*!|>'"%@`\-]/,ue=Tn(["\r",` +`," "," ","?",":",",","]","[","{","}","#","&","*","!","|",">","'",'"',"%","@","`","-"],!0,!1),pe=/^[^\r\n\t ,\][{}:#"']/,ke=Tn(["\r",` +`," "," ",",","]","[","{","}",":","#",'"',"'"],!0,!1),Fe=function(){return pg().replace(/^ *| *$/g,"")},Ne="--",oe=ar("--",!1),le=/^[a-zA-Z\/0-9]/,Be=Tn([["a","z"],["A","Z"],"/",["0","9"]],!1,!1),fe=/^[^\r\n\t :,]/,ae=Tn(["\r",` +`," "," ",":",","],!0,!1),qe="null",ne=ar("null",!1),Y=function(){return null},he="true",ie=ar("true",!1),de=function(){return!0},_e="false",Pt=ar("false",!1),It=function(){return!1},Mr=Us("string"),ii='"',gi=ar('"',!1),hr=function(){return""},fi=function(R){return R},ni=function(R){return R.join("")},Ks=/^[^"\\\0-\x1F\x7F]/,pr=Tn(['"',"\\",["\0",""],"\x7F"],!0,!1),Ii='\\"',rs=ar('\\"',!1),fa=function(){return'"'},dA="\\\\",cg=ar("\\\\",!1),is=function(){return"\\"},CA="\\/",ha=ar("\\/",!1),wp=function(){return"/"},mA="\\b",EA=ar("\\b",!1),wr=function(){return"\b"},Tl="\\f",ug=ar("\\f",!1),yo=function(){return"\f"},gg="\\n",Bp=ar("\\n",!1),bp=function(){return` +`},vr="\\r",se=ar("\\r",!1),wo=function(){return"\r"},Fn="\\t",fg=ar("\\t",!1),bt=function(){return" "},Ll="\\u",Nn=ar("\\u",!1),ns=function(R,q,Ce,Ke){return String.fromCharCode(parseInt(`0x${R}${q}${Ce}${Ke}`))},ss=/^[0-9a-fA-F]/,gt=Tn([["0","9"],["a","f"],["A","F"]],!1,!1),Bo=Us("blank space"),At=/^[ \t]/,ln=Tn([" "," "],!1,!1),S=Us("white space"),Lt=/^[ \t\n\r]/,hg=Tn([" "," ",` +`,"\r"],!1,!1),Ml=`\r +`,Qp=ar(`\r +`,!1),Sp=` +`,vp=ar(` +`,!1),xp="\r",Pp=ar("\r",!1),G=0,yt=0,IA=[{line:1,column:1}],zi=0,Ol=[],Xe=0,pa;if("startRule"in e){if(!(e.startRule in i))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');n=i[e.startRule]}function pg(){return r.substring(yt,G)}function ME(){return cn(yt,G)}function Dp(R,q){throw q=q!==void 0?q:cn(yt,G),Ul([Us(R)],r.substring(yt,G),q)}function OE(R,q){throw q=q!==void 0?q:cn(yt,G),dg(R,q)}function ar(R,q){return{type:"literal",text:R,ignoreCase:q}}function Tn(R,q,Ce){return{type:"class",parts:R,inverted:q,ignoreCase:Ce}}function Kl(){return{type:"any"}}function kp(){return{type:"end"}}function Us(R){return{type:"other",description:R}}function da(R){var q=IA[R],Ce;if(q)return q;for(Ce=R-1;!IA[Ce];)Ce--;for(q=IA[Ce],q={line:q.line,column:q.column};Cezi&&(zi=G,Ol=[]),Ol.push(R))}function dg(R,q){return new ac(R,null,null,q)}function Ul(R,q,Ce){return new ac(ac.buildMessage(R,q),R,q,Ce)}function Hs(){var R;return R=Cg(),R}function Hl(){var R,q,Ce;for(R=G,q=[],Ce=yA();Ce!==t;)q.push(Ce),Ce=yA();return q!==t&&(yt=R,q=s(q)),R=q,R}function yA(){var R,q,Ce,Ke,Re;return R=G,q=ma(),q!==t?(r.charCodeAt(G)===45?(Ce=o,G++):(Ce=t,Xe===0&&Le(a)),Ce!==t?(Ke=Rr(),Ke!==t?(Re=Ca(),Re!==t?(yt=R,q=l(Re),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R}function Cg(){var R,q,Ce;for(R=G,q=[],Ce=mg();Ce!==t;)q.push(Ce),Ce=mg();return q!==t&&(yt=R,q=c(q)),R=q,R}function mg(){var R,q,Ce,Ke,Re,ze,dt,Ft,Ln;if(R=G,q=Rr(),q===t&&(q=null),q!==t){if(Ce=G,r.charCodeAt(G)===35?(Ke=u,G++):(Ke=t,Xe===0&&Le(g)),Ke!==t){if(Re=[],ze=G,dt=G,Xe++,Ft=js(),Xe--,Ft===t?dt=void 0:(G=dt,dt=t),dt!==t?(r.length>G?(Ft=r.charAt(G),G++):(Ft=t,Xe===0&&Le(f)),Ft!==t?(dt=[dt,Ft],ze=dt):(G=ze,ze=t)):(G=ze,ze=t),ze!==t)for(;ze!==t;)Re.push(ze),ze=G,dt=G,Xe++,Ft=js(),Xe--,Ft===t?dt=void 0:(G=dt,dt=t),dt!==t?(r.length>G?(Ft=r.charAt(G),G++):(Ft=t,Xe===0&&Le(f)),Ft!==t?(dt=[dt,Ft],ze=dt):(G=ze,ze=t)):(G=ze,ze=t);else Re=t;Re!==t?(Ke=[Ke,Re],Ce=Ke):(G=Ce,Ce=t)}else G=Ce,Ce=t;if(Ce===t&&(Ce=null),Ce!==t){if(Ke=[],Re=Ys(),Re!==t)for(;Re!==t;)Ke.push(Re),Re=Ys();else Ke=t;Ke!==t?(yt=R,q=h(),R=q):(G=R,R=t)}else G=R,R=t}else G=R,R=t;if(R===t&&(R=G,q=ma(),q!==t?(Ce=Gl(),Ce!==t?(Ke=Rr(),Ke===t&&(Ke=null),Ke!==t?(r.charCodeAt(G)===58?(Re=p,G++):(Re=t,Xe===0&&Le(C)),Re!==t?(ze=Rr(),ze===t&&(ze=null),ze!==t?(dt=Ca(),dt!==t?(yt=R,q=y(Ce,dt),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t&&(R=G,q=ma(),q!==t?(Ce=Gs(),Ce!==t?(Ke=Rr(),Ke===t&&(Ke=null),Ke!==t?(r.charCodeAt(G)===58?(Re=p,G++):(Re=t,Xe===0&&Le(C)),Re!==t?(ze=Rr(),ze===t&&(ze=null),ze!==t?(dt=Ca(),dt!==t?(yt=R,q=y(Ce,dt),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t))){if(R=G,q=ma(),q!==t)if(Ce=Gs(),Ce!==t)if(Ke=Rr(),Ke!==t)if(Re=KE(),Re!==t){if(ze=[],dt=Ys(),dt!==t)for(;dt!==t;)ze.push(dt),dt=Ys();else ze=t;ze!==t?(yt=R,q=y(Ce,Re),R=q):(G=R,R=t)}else G=R,R=t;else G=R,R=t;else G=R,R=t;else G=R,R=t;if(R===t)if(R=G,q=ma(),q!==t)if(Ce=Gs(),Ce!==t){if(Ke=[],Re=G,ze=Rr(),ze===t&&(ze=null),ze!==t?(r.charCodeAt(G)===44?(dt=B,G++):(dt=t,Xe===0&&Le(v)),dt!==t?(Ft=Rr(),Ft===t&&(Ft=null),Ft!==t?(Ln=Gs(),Ln!==t?(yt=Re,ze=D(Ce,Ln),Re=ze):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t),Re!==t)for(;Re!==t;)Ke.push(Re),Re=G,ze=Rr(),ze===t&&(ze=null),ze!==t?(r.charCodeAt(G)===44?(dt=B,G++):(dt=t,Xe===0&&Le(v)),dt!==t?(Ft=Rr(),Ft===t&&(Ft=null),Ft!==t?(Ln=Gs(),Ln!==t?(yt=Re,ze=D(Ce,Ln),Re=ze):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t)):(G=Re,Re=t);else Ke=t;Ke!==t?(Re=Rr(),Re===t&&(Re=null),Re!==t?(r.charCodeAt(G)===58?(ze=p,G++):(ze=t,Xe===0&&Le(C)),ze!==t?(dt=Rr(),dt===t&&(dt=null),dt!==t?(Ft=Ca(),Ft!==t?(yt=R,q=T(Ce,Ke,Ft),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)}else G=R,R=t;else G=R,R=t}return R}function Ca(){var R,q,Ce,Ke,Re,ze,dt;if(R=G,q=G,Xe++,Ce=G,Ke=js(),Ke!==t?(Re=rt(),Re!==t?(r.charCodeAt(G)===45?(ze=o,G++):(ze=t,Xe===0&&Le(a)),ze!==t?(dt=Rr(),dt!==t?(Ke=[Ke,Re,ze,dt],Ce=Ke):(G=Ce,Ce=t)):(G=Ce,Ce=t)):(G=Ce,Ce=t)):(G=Ce,Ce=t),Xe--,Ce!==t?(G=q,q=void 0):q=t,q!==t?(Ce=Ys(),Ce!==t?(Ke=bo(),Ke!==t?(Re=Hl(),Re!==t?(ze=wA(),ze!==t?(yt=R,q=H(Re),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t&&(R=G,q=js(),q!==t?(Ce=bo(),Ce!==t?(Ke=Cg(),Ke!==t?(Re=wA(),Re!==t?(yt=R,q=H(Ke),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t),R===t))if(R=G,q=Yl(),q!==t){if(Ce=[],Ke=Ys(),Ke!==t)for(;Ke!==t;)Ce.push(Ke),Ke=Ys();else Ce=t;Ce!==t?(yt=R,q=j(q),R=q):(G=R,R=t)}else G=R,R=t;return R}function ma(){var R,q,Ce;for(Xe++,R=G,q=[],r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));Ce!==t;)q.push(Ce),r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));return q!==t?(yt=G,Ce=_(q),Ce?Ce=void 0:Ce=t,Ce!==t?(q=[q,Ce],R=q):(G=R,R=t)):(G=R,R=t),Xe--,R===t&&(q=t,Xe===0&&Le($)),R}function rt(){var R,q,Ce;for(R=G,q=[],r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));Ce!==t;)q.push(Ce),r.charCodeAt(G)===32?(Ce=V,G++):(Ce=t,Xe===0&&Le(W));return q!==t?(yt=G,Ce=A(q),Ce?Ce=void 0:Ce=t,Ce!==t?(q=[q,Ce],R=q):(G=R,R=t)):(G=R,R=t),R}function bo(){var R;return yt=G,R=Ae(),R?R=void 0:R=t,R}function wA(){var R;return yt=G,R=ge(),R?R=void 0:R=t,R}function Gl(){var R;return R=jl(),R===t&&(R=Rp()),R}function Gs(){var R,q,Ce;if(R=jl(),R===t){if(R=G,q=[],Ce=Eg(),Ce!==t)for(;Ce!==t;)q.push(Ce),Ce=Eg();else q=t;q!==t&&(yt=R,q=re()),R=q}return R}function Yl(){var R;return R=Fp(),R===t&&(R=UE(),R===t&&(R=jl(),R===t&&(R=Rp()))),R}function KE(){var R;return R=Fp(),R===t&&(R=jl(),R===t&&(R=Eg())),R}function Rp(){var R,q,Ce,Ke,Re,ze;if(Xe++,R=G,F.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(ue)),q!==t){for(Ce=[],Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(pe.test(r.charAt(G))?(ze=r.charAt(G),G++):(ze=t,Xe===0&&Le(ke)),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ke!==t;)Ce.push(Ke),Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(pe.test(r.charAt(G))?(ze=r.charAt(G),G++):(ze=t,Xe===0&&Le(ke)),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ce!==t?(yt=R,q=Fe(),R=q):(G=R,R=t)}else G=R,R=t;return Xe--,R===t&&(q=t,Xe===0&&Le(M)),R}function Eg(){var R,q,Ce,Ke,Re;if(R=G,r.substr(G,2)===Ne?(q=Ne,G+=2):(q=t,Xe===0&&Le(oe)),q===t&&(q=null),q!==t)if(le.test(r.charAt(G))?(Ce=r.charAt(G),G++):(Ce=t,Xe===0&&Le(Be)),Ce!==t){for(Ke=[],fe.test(r.charAt(G))?(Re=r.charAt(G),G++):(Re=t,Xe===0&&Le(ae));Re!==t;)Ke.push(Re),fe.test(r.charAt(G))?(Re=r.charAt(G),G++):(Re=t,Xe===0&&Le(ae));Ke!==t?(yt=R,q=Fe(),R=q):(G=R,R=t)}else G=R,R=t;else G=R,R=t;return R}function Fp(){var R,q;return R=G,r.substr(G,4)===qe?(q=qe,G+=4):(q=t,Xe===0&&Le(ne)),q!==t&&(yt=R,q=Y()),R=q,R}function UE(){var R,q;return R=G,r.substr(G,4)===he?(q=he,G+=4):(q=t,Xe===0&&Le(ie)),q!==t&&(yt=R,q=de()),R=q,R===t&&(R=G,r.substr(G,5)===_e?(q=_e,G+=5):(q=t,Xe===0&&Le(Pt)),q!==t&&(yt=R,q=It()),R=q),R}function jl(){var R,q,Ce,Ke;return Xe++,R=G,r.charCodeAt(G)===34?(q=ii,G++):(q=t,Xe===0&&Le(gi)),q!==t?(r.charCodeAt(G)===34?(Ce=ii,G++):(Ce=t,Xe===0&&Le(gi)),Ce!==t?(yt=R,q=hr(),R=q):(G=R,R=t)):(G=R,R=t),R===t&&(R=G,r.charCodeAt(G)===34?(q=ii,G++):(q=t,Xe===0&&Le(gi)),q!==t?(Ce=HE(),Ce!==t?(r.charCodeAt(G)===34?(Ke=ii,G++):(Ke=t,Xe===0&&Le(gi)),Ke!==t?(yt=R,q=fi(Ce),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)),Xe--,R===t&&(q=t,Xe===0&&Le(Mr)),R}function HE(){var R,q,Ce;if(R=G,q=[],Ce=Ig(),Ce!==t)for(;Ce!==t;)q.push(Ce),Ce=Ig();else q=t;return q!==t&&(yt=R,q=ni(q)),R=q,R}function Ig(){var R,q,Ce,Ke,Re,ze;return Ks.test(r.charAt(G))?(R=r.charAt(G),G++):(R=t,Xe===0&&Le(pr)),R===t&&(R=G,r.substr(G,2)===Ii?(q=Ii,G+=2):(q=t,Xe===0&&Le(rs)),q!==t&&(yt=R,q=fa()),R=q,R===t&&(R=G,r.substr(G,2)===dA?(q=dA,G+=2):(q=t,Xe===0&&Le(cg)),q!==t&&(yt=R,q=is()),R=q,R===t&&(R=G,r.substr(G,2)===CA?(q=CA,G+=2):(q=t,Xe===0&&Le(ha)),q!==t&&(yt=R,q=wp()),R=q,R===t&&(R=G,r.substr(G,2)===mA?(q=mA,G+=2):(q=t,Xe===0&&Le(EA)),q!==t&&(yt=R,q=wr()),R=q,R===t&&(R=G,r.substr(G,2)===Tl?(q=Tl,G+=2):(q=t,Xe===0&&Le(ug)),q!==t&&(yt=R,q=yo()),R=q,R===t&&(R=G,r.substr(G,2)===gg?(q=gg,G+=2):(q=t,Xe===0&&Le(Bp)),q!==t&&(yt=R,q=bp()),R=q,R===t&&(R=G,r.substr(G,2)===vr?(q=vr,G+=2):(q=t,Xe===0&&Le(se)),q!==t&&(yt=R,q=wo()),R=q,R===t&&(R=G,r.substr(G,2)===Fn?(q=Fn,G+=2):(q=t,Xe===0&&Le(fg)),q!==t&&(yt=R,q=bt()),R=q,R===t&&(R=G,r.substr(G,2)===Ll?(q=Ll,G+=2):(q=t,Xe===0&&Le(Nn)),q!==t?(Ce=BA(),Ce!==t?(Ke=BA(),Ke!==t?(Re=BA(),Re!==t?(ze=BA(),ze!==t?(yt=R,q=ns(Ce,Ke,Re,ze),R=q):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)):(G=R,R=t)))))))))),R}function BA(){var R;return ss.test(r.charAt(G))?(R=r.charAt(G),G++):(R=t,Xe===0&&Le(gt)),R}function Rr(){var R,q;if(Xe++,R=[],At.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(ln)),q!==t)for(;q!==t;)R.push(q),At.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(ln));else R=t;return Xe--,R===t&&(q=t,Xe===0&&Le(Bo)),R}function GE(){var R,q;if(Xe++,R=[],Lt.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(hg)),q!==t)for(;q!==t;)R.push(q),Lt.test(r.charAt(G))?(q=r.charAt(G),G++):(q=t,Xe===0&&Le(hg));else R=t;return Xe--,R===t&&(q=t,Xe===0&&Le(S)),R}function Ys(){var R,q,Ce,Ke,Re,ze;if(R=G,q=js(),q!==t){for(Ce=[],Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(ze=js(),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ke!==t;)Ce.push(Ke),Ke=G,Re=Rr(),Re===t&&(Re=null),Re!==t?(ze=js(),ze!==t?(Re=[Re,ze],Ke=Re):(G=Ke,Ke=t)):(G=Ke,Ke=t);Ce!==t?(q=[q,Ce],R=q):(G=R,R=t)}else G=R,R=t;return R}function js(){var R;return r.substr(G,2)===Ml?(R=Ml,G+=2):(R=t,Xe===0&&Le(Qp)),R===t&&(r.charCodeAt(G)===10?(R=Sp,G++):(R=t,Xe===0&&Le(vp)),R===t&&(r.charCodeAt(G)===13?(R=xp,G++):(R=t,Xe===0&&Le(Pp)))),R}let yg=2,bA=0;if(pa=n(),pa!==t&&G===r.length)return pa;throw pa!==t&&G{"use strict";var hde=r=>{let e=!1,t=!1,i=!1;for(let n=0;n{if(!(typeof r=="string"||Array.isArray(r)))throw new TypeError("Expected the input to be `string | string[]`");e=Object.assign({pascalCase:!1},e);let t=n=>e.pascalCase?n.charAt(0).toUpperCase()+n.slice(1):n;return Array.isArray(r)?r=r.map(n=>n.trim()).filter(n=>n.length).join("-"):r=r.trim(),r.length===0?"":r.length===1?e.pascalCase?r.toUpperCase():r.toLowerCase():(r!==r.toLowerCase()&&(r=hde(r)),r=r.replace(/^[_.\- ]+/,"").toLowerCase().replace(/[_.\- ]+(\w|$)/g,(n,s)=>s.toUpperCase()).replace(/\d+(\w|$)/g,n=>n.toUpperCase()),t(r))};ev.exports=hH;ev.exports.default=hH});var dH=w((A_e,pde)=>{pde.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:"Appcircle",constant:"APPCIRCLE",env:"AC_APPCIRCLE"},{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:"Codefresh",constant:"CODEFRESH",env:"CF_BUILD_ID",pr:{any:["CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_ID"]}},{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:"GitHub Actions",constant:"GITHUB_ACTIONS",env:"GITHUB_ACTIONS",pr:{GITHUB_EVENT_NAME:"pull_request"}},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI",pr:"CI_MERGE_REQUEST_ID"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"LayerCI",constant:"LAYERCI",env:"LAYERCI",pr:"LAYERCI_PULL_REQUEST"},{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",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Nevercode",constant:"NEVERCODE",env:"NEVERCODE",pr:{env:"NEVERCODE_PULL_REQUEST",ne:"false"}},{name:"Render",constant:"RENDER",env:"RENDER",pr:{IS_PULL_REQUEST:"true"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Screwdriver",constant:"SCREWDRIVER",env:"SCREWDRIVER",pr:{env:"SD_PULL_REQUEST",ne:"false"}},{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"}},{name:"Vercel",constant:"VERCEL",env:"NOW_BUILDER"},{name:"Visual Studio App Center",constant:"APPCENTER",env:"APPCENTER_BUILD_ID"}]});var Ac=w(Un=>{"use strict";var mH=dH(),Po=process.env;Object.defineProperty(Un,"_vendors",{value:mH.map(function(r){return r.constant})});Un.name=null;Un.isPR=null;mH.forEach(function(r){let t=(Array.isArray(r.env)?r.env:[r.env]).every(function(i){return CH(i)});if(Un[r.constant]=t,t)switch(Un.name=r.name,typeof r.pr){case"string":Un.isPR=!!Po[r.pr];break;case"object":"env"in r.pr?Un.isPR=r.pr.env in Po&&Po[r.pr.env]!==r.pr.ne:"any"in r.pr?Un.isPR=r.pr.any.some(function(i){return!!Po[i]}):Un.isPR=CH(r.pr);break;default:Un.isPR=null}});Un.isCI=!!(Po.CI||Po.CONTINUOUS_INTEGRATION||Po.BUILD_NUMBER||Po.RUN_ID||Un.name);function CH(r){return typeof r=="string"?!!Po[r]:Object.keys(r).every(function(e){return Po[e]===r[e]})}});var hn={};ut(hn,{KeyRelationship:()=>lc,applyCascade:()=>od,base64RegExp:()=>BH,colorStringAlphaRegExp:()=>wH,colorStringRegExp:()=>yH,computeKey:()=>RA,getPrintable:()=>Vr,hasExactLength:()=>xH,hasForbiddenKeys:()=>Wde,hasKeyRelationship:()=>av,hasMaxLength:()=>Dde,hasMinLength:()=>Pde,hasMutuallyExclusiveKeys:()=>zde,hasRequiredKeys:()=>Jde,hasUniqueItems:()=>kde,isArray:()=>yde,isAtLeast:()=>Nde,isAtMost:()=>Tde,isBase64:()=>jde,isBoolean:()=>mde,isDate:()=>Ide,isDict:()=>Bde,isEnum:()=>Zi,isHexColor:()=>Yde,isISO8601:()=>Gde,isInExclusiveRange:()=>Mde,isInInclusiveRange:()=>Lde,isInstanceOf:()=>Qde,isInteger:()=>Ode,isJSON:()=>qde,isLiteral:()=>dde,isLowerCase:()=>Kde,isNegative:()=>Rde,isNullable:()=>xde,isNumber:()=>Ede,isObject:()=>bde,isOneOf:()=>Sde,isOptional:()=>vde,isPositive:()=>Fde,isString:()=>sd,isTuple:()=>wde,isUUID4:()=>Hde,isUnknown:()=>vH,isUpperCase:()=>Ude,iso8601RegExp:()=>ov,makeCoercionFn:()=>cc,makeSetter:()=>SH,makeTrait:()=>QH,makeValidator:()=>Qt,matchesRegExp:()=>ad,plural:()=>kI,pushError:()=>pt,simpleKeyRegExp:()=>IH,uuid4RegExp:()=>bH});function Qt({test:r}){return QH(r)()}function Vr(r){return r===null?"null":r===void 0?"undefined":r===""?"an empty string":JSON.stringify(r)}function RA(r,e){var t,i,n;return typeof e=="number"?`${(t=r==null?void 0:r.p)!==null&&t!==void 0?t:"."}[${e}]`:IH.test(e)?`${(i=r==null?void 0:r.p)!==null&&i!==void 0?i:""}.${e}`:`${(n=r==null?void 0:r.p)!==null&&n!==void 0?n:"."}[${JSON.stringify(e)}]`}function cc(r,e){return t=>{let i=r[e];return r[e]=t,cc(r,e).bind(null,i)}}function SH(r,e){return t=>{r[e]=t}}function kI(r,e,t){return r===1?e:t}function pt({errors:r,p:e}={},t){return r==null||r.push(`${e!=null?e:"."}: ${t}`),!1}function dde(r){return Qt({test:(e,t)=>e!==r?pt(t,`Expected a literal (got ${Vr(r)})`):!0})}function Zi(r){let e=Array.isArray(r)?r:Object.values(r),t=new Set(e);return Qt({test:(i,n)=>t.has(i)?!0:pt(n,`Expected a valid enumeration value (got ${Vr(i)})`)})}var IH,yH,wH,BH,bH,ov,QH,vH,sd,Cde,mde,Ede,Ide,yde,wde,Bde,bde,Qde,Sde,od,vde,xde,Pde,Dde,xH,kde,Rde,Fde,Nde,Tde,Lde,Mde,Ode,ad,Kde,Ude,Hde,Gde,Yde,jde,qde,Jde,Wde,zde,lc,Vde,av,ls=Tge(()=>{IH=/^[a-zA-Z_][a-zA-Z0-9_]*$/,yH=/^#[0-9a-f]{6}$/i,wH=/^#[0-9a-f]{6}([0-9a-f]{2})?$/i,BH=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,bH=/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}$/i,ov=/^(?:[1-9]\d{3}(-?)(?:(?:0[1-9]|1[0-2])\1(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])\1(?:29|30)|(?:0[13578]|1[02])(?:\1)31|00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[0-5]))|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)(?:(-?)02(?:\2)29|-?366))T(?:[01]\d|2[0-3])(:?)[0-5]\d(?:\3[0-5]\d)?(?:Z|[+-][01]\d(?:\3[0-5]\d)?)$/,QH=r=>()=>r;vH=()=>Qt({test:(r,e)=>!0});sd=()=>Qt({test:(r,e)=>typeof r!="string"?pt(e,`Expected a string (got ${Vr(r)})`):!0});Cde=new Map([["true",!0],["True",!0],["1",!0],[1,!0],["false",!1],["False",!1],["0",!1],[0,!1]]),mde=()=>Qt({test:(r,e)=>{var t;if(typeof r!="boolean"){if(typeof(e==null?void 0:e.coercions)<"u"){if(typeof(e==null?void 0:e.coercion)>"u")return pt(e,"Unbound coercion result");let i=Cde.get(r);if(typeof i<"u")return e.coercions.push([(t=e.p)!==null&&t!==void 0?t:".",e.coercion.bind(null,i)]),!0}return pt(e,`Expected a boolean (got ${Vr(r)})`)}return!0}}),Ede=()=>Qt({test:(r,e)=>{var t;if(typeof r!="number"){if(typeof(e==null?void 0:e.coercions)<"u"){if(typeof(e==null?void 0:e.coercion)>"u")return pt(e,"Unbound coercion result");let i;if(typeof r=="string"){let n;try{n=JSON.parse(r)}catch{}if(typeof n=="number")if(JSON.stringify(n)===r)i=n;else return pt(e,`Received a number that can't be safely represented by the runtime (${r})`)}if(typeof i<"u")return e.coercions.push([(t=e.p)!==null&&t!==void 0?t:".",e.coercion.bind(null,i)]),!0}return pt(e,`Expected a number (got ${Vr(r)})`)}return!0}}),Ide=()=>Qt({test:(r,e)=>{var t;if(!(r instanceof Date)){if(typeof(e==null?void 0:e.coercions)<"u"){if(typeof(e==null?void 0:e.coercion)>"u")return pt(e,"Unbound coercion result");let i;if(typeof r=="string"&&ov.test(r))i=new Date(r);else{let n;if(typeof r=="string"){let s;try{s=JSON.parse(r)}catch{}typeof s=="number"&&(n=s)}else typeof r=="number"&&(n=r);if(typeof n<"u")if(Number.isSafeInteger(n)||!Number.isSafeInteger(n*1e3))i=new Date(n*1e3);else return pt(e,`Received a timestamp that can't be safely represented by the runtime (${r})`)}if(typeof i<"u")return e.coercions.push([(t=e.p)!==null&&t!==void 0?t:".",e.coercion.bind(null,i)]),!0}return pt(e,`Expected a date (got ${Vr(r)})`)}return!0}}),yde=(r,{delimiter:e}={})=>Qt({test:(t,i)=>{var n;if(typeof t=="string"&&typeof e<"u"&&typeof(i==null?void 0:i.coercions)<"u"){if(typeof(i==null?void 0:i.coercion)>"u")return pt(i,"Unbound coercion result");t=t.split(e),i.coercions.push([(n=i.p)!==null&&n!==void 0?n:".",i.coercion.bind(null,t)])}if(!Array.isArray(t))return pt(i,`Expected an array (got ${Vr(t)})`);let s=!0;for(let o=0,a=t.length;o{let t=xH(r.length);return Qt({test:(i,n)=>{var s;if(typeof i=="string"&&typeof e<"u"&&typeof(n==null?void 0:n.coercions)<"u"){if(typeof(n==null?void 0:n.coercion)>"u")return pt(n,"Unbound coercion result");i=i.split(e),n.coercions.push([(s=n.p)!==null&&s!==void 0?s:".",n.coercion.bind(null,i)])}if(!Array.isArray(i))return pt(n,`Expected a tuple (got ${Vr(i)})`);let o=t(i,Object.assign({},n));for(let a=0,l=i.length;aQt({test:(t,i)=>{if(typeof t!="object"||t===null)return pt(i,`Expected an object (got ${Vr(t)})`);let n=Object.keys(t),s=!0;for(let o=0,a=n.length;o{let t=Object.keys(r);return Qt({test:(i,n)=>{if(typeof i!="object"||i===null)return pt(n,`Expected an object (got ${Vr(i)})`);let s=new Set([...t,...Object.keys(i)]),o={},a=!0;for(let l of s){if(l==="constructor"||l==="__proto__")a=pt(Object.assign(Object.assign({},n),{p:RA(n,l)}),"Unsafe property name");else{let c=Object.prototype.hasOwnProperty.call(r,l)?r[l]:void 0,u=Object.prototype.hasOwnProperty.call(i,l)?i[l]:void 0;typeof c<"u"?a=c(u,Object.assign(Object.assign({},n),{p:RA(n,l),coercion:cc(i,l)}))&&a:e===null?a=pt(Object.assign(Object.assign({},n),{p:RA(n,l)}),`Extraneous property (got ${Vr(u)})`):Object.defineProperty(o,l,{enumerable:!0,get:()=>u,set:SH(i,l)})}if(!a&&(n==null?void 0:n.errors)==null)break}return e!==null&&(a||(n==null?void 0:n.errors)!=null)&&(a=e(o,n)&&a),a}})},Qde=r=>Qt({test:(e,t)=>e instanceof r?!0:pt(t,`Expected an instance of ${r.name} (got ${Vr(e)})`)}),Sde=(r,{exclusive:e=!1}={})=>Qt({test:(t,i)=>{var n,s,o;let a=[],l=typeof(i==null?void 0:i.errors)<"u"?[]:void 0;for(let c=0,u=r.length;c1?pt(i,`Expected to match exactly a single predicate (matched ${a.join(", ")})`):(o=i==null?void 0:i.errors)===null||o===void 0||o.push(...l),!1}}),od=(r,e)=>Qt({test:(t,i)=>{var n,s;let o={value:t},a=typeof(i==null?void 0:i.coercions)<"u"?cc(o,"value"):void 0,l=typeof(i==null?void 0:i.coercions)<"u"?[]:void 0;if(!r(t,Object.assign(Object.assign({},i),{coercion:a,coercions:l})))return!1;let c=[];if(typeof l<"u")for(let[,u]of l)c.push(u());try{if(typeof(i==null?void 0:i.coercions)<"u"){if(o.value!==t){if(typeof(i==null?void 0:i.coercion)>"u")return pt(i,"Unbound coercion result");i.coercions.push([(n=i.p)!==null&&n!==void 0?n:".",i.coercion.bind(null,o.value)])}(s=i==null?void 0:i.coercions)===null||s===void 0||s.push(...l)}return e.every(u=>u(o.value,i))}finally{for(let u of c)u()}}}),vde=r=>Qt({test:(e,t)=>typeof e>"u"?!0:r(e,t)}),xde=r=>Qt({test:(e,t)=>e===null?!0:r(e,t)}),Pde=r=>Qt({test:(e,t)=>e.length>=r?!0:pt(t,`Expected to have a length of at least ${r} elements (got ${e.length})`)}),Dde=r=>Qt({test:(e,t)=>e.length<=r?!0:pt(t,`Expected to have a length of at most ${r} elements (got ${e.length})`)}),xH=r=>Qt({test:(e,t)=>e.length!==r?pt(t,`Expected to have a length of exactly ${r} elements (got ${e.length})`):!0}),kde=({map:r}={})=>Qt({test:(e,t)=>{let i=new Set,n=new Set;for(let s=0,o=e.length;sQt({test:(r,e)=>r<=0?!0:pt(e,`Expected to be negative (got ${r})`)}),Fde=()=>Qt({test:(r,e)=>r>=0?!0:pt(e,`Expected to be positive (got ${r})`)}),Nde=r=>Qt({test:(e,t)=>e>=r?!0:pt(t,`Expected to be at least ${r} (got ${e})`)}),Tde=r=>Qt({test:(e,t)=>e<=r?!0:pt(t,`Expected to be at most ${r} (got ${e})`)}),Lde=(r,e)=>Qt({test:(t,i)=>t>=r&&t<=e?!0:pt(i,`Expected to be in the [${r}; ${e}] range (got ${t})`)}),Mde=(r,e)=>Qt({test:(t,i)=>t>=r&&tQt({test:(e,t)=>e!==Math.round(e)?pt(t,`Expected to be an integer (got ${e})`):Number.isSafeInteger(e)?!0:pt(t,`Expected to be a safe integer (got ${e})`)}),ad=r=>Qt({test:(e,t)=>r.test(e)?!0:pt(t,`Expected to match the pattern ${r.toString()} (got ${Vr(e)})`)}),Kde=()=>Qt({test:(r,e)=>r!==r.toLowerCase()?pt(e,`Expected to be all-lowercase (got ${r})`):!0}),Ude=()=>Qt({test:(r,e)=>r!==r.toUpperCase()?pt(e,`Expected to be all-uppercase (got ${r})`):!0}),Hde=()=>Qt({test:(r,e)=>bH.test(r)?!0:pt(e,`Expected to be a valid UUID v4 (got ${Vr(r)})`)}),Gde=()=>Qt({test:(r,e)=>ov.test(r)?!1:pt(e,`Expected to be a valid ISO 8601 date string (got ${Vr(r)})`)}),Yde=({alpha:r=!1})=>Qt({test:(e,t)=>(r?yH.test(e):wH.test(e))?!0:pt(t,`Expected to be a valid hexadecimal color string (got ${Vr(e)})`)}),jde=()=>Qt({test:(r,e)=>BH.test(r)?!0:pt(e,`Expected to be a valid base 64 string (got ${Vr(r)})`)}),qde=(r=vH())=>Qt({test:(e,t)=>{let i;try{i=JSON.parse(e)}catch{return pt(t,`Expected to be a valid JSON string (got ${Vr(e)})`)}return r(i,t)}}),Jde=r=>{let e=new Set(r);return Qt({test:(t,i)=>{let n=new Set(Object.keys(t)),s=[];for(let o of e)n.has(o)||s.push(o);return s.length>0?pt(i,`Missing required ${kI(s.length,"property","properties")} ${s.map(o=>`"${o}"`).join(", ")}`):!0}})},Wde=r=>{let e=new Set(r);return Qt({test:(t,i)=>{let n=new Set(Object.keys(t)),s=[];for(let o of e)n.has(o)&&s.push(o);return s.length>0?pt(i,`Forbidden ${kI(s.length,"property","properties")} ${s.map(o=>`"${o}"`).join(", ")}`):!0}})},zde=r=>{let e=new Set(r);return Qt({test:(t,i)=>{let n=new Set(Object.keys(t)),s=[];for(let o of e)n.has(o)&&s.push(o);return s.length>1?pt(i,`Mutually exclusive properties ${s.map(o=>`"${o}"`).join(", ")}`):!0}})};(function(r){r.Forbids="Forbids",r.Requires="Requires"})(lc||(lc={}));Vde={[lc.Forbids]:{expect:!1,message:"forbids using"},[lc.Requires]:{expect:!0,message:"requires using"}},av=(r,e,t,{ignore:i=[]}={})=>{let n=new Set(i),s=new Set(t),o=Vde[e];return Qt({test:(a,l)=>{let c=new Set(Object.keys(a));if(!c.has(r)||n.has(a[r]))return!0;let u=[];for(let g of s)(c.has(g)&&!n.has(a[g]))!==o.expect&&u.push(g);return u.length>=1?pt(l,`Property "${r}" ${o.message} ${kI(u.length,"property","properties")} ${u.map(g=>`"${g}"`).join(", ")}`):!0}})}});var qH=w((A$e,jH)=>{"use strict";jH.exports=(r,...e)=>new Promise(t=>{t(r(...e))})});var Jg=w((l$e,pv)=>{"use strict";var gCe=qH(),JH=r=>{if(r<1)throw new TypeError("Expected `concurrency` to be a number from 1 and up");let e=[],t=0,i=()=>{t--,e.length>0&&e.shift()()},n=(a,l,...c)=>{t++;let u=gCe(a,...c);l(u),u.then(i,i)},s=(a,l,...c)=>{tnew Promise(c=>s(a,c,...l));return Object.defineProperties(o,{activeCount:{get:()=>t},pendingCount:{get:()=>e.length}}),o};pv.exports=JH;pv.exports.default=JH});var gd=w((u$e,WH)=>{var fCe="2.0.0",hCe=Number.MAX_SAFE_INTEGER||9007199254740991,pCe=16;WH.exports={SEMVER_SPEC_VERSION:fCe,MAX_LENGTH:256,MAX_SAFE_INTEGER:hCe,MAX_SAFE_COMPONENT_LENGTH:pCe}});var fd=w((g$e,zH)=>{var dCe=typeof process=="object"&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...r)=>console.error("SEMVER",...r):()=>{};zH.exports=dCe});var uc=w((NA,VH)=>{var{MAX_SAFE_COMPONENT_LENGTH:dv}=gd(),CCe=fd();NA=VH.exports={};var mCe=NA.re=[],et=NA.src=[],tt=NA.t={},ECe=0,St=(r,e,t)=>{let i=ECe++;CCe(i,e),tt[r]=i,et[i]=e,mCe[i]=new RegExp(e,t?"g":void 0)};St("NUMERICIDENTIFIER","0|[1-9]\\d*");St("NUMERICIDENTIFIERLOOSE","[0-9]+");St("NONNUMERICIDENTIFIER","\\d*[a-zA-Z-][a-zA-Z0-9-]*");St("MAINVERSION",`(${et[tt.NUMERICIDENTIFIER]})\\.(${et[tt.NUMERICIDENTIFIER]})\\.(${et[tt.NUMERICIDENTIFIER]})`);St("MAINVERSIONLOOSE",`(${et[tt.NUMERICIDENTIFIERLOOSE]})\\.(${et[tt.NUMERICIDENTIFIERLOOSE]})\\.(${et[tt.NUMERICIDENTIFIERLOOSE]})`);St("PRERELEASEIDENTIFIER",`(?:${et[tt.NUMERICIDENTIFIER]}|${et[tt.NONNUMERICIDENTIFIER]})`);St("PRERELEASEIDENTIFIERLOOSE",`(?:${et[tt.NUMERICIDENTIFIERLOOSE]}|${et[tt.NONNUMERICIDENTIFIER]})`);St("PRERELEASE",`(?:-(${et[tt.PRERELEASEIDENTIFIER]}(?:\\.${et[tt.PRERELEASEIDENTIFIER]})*))`);St("PRERELEASELOOSE",`(?:-?(${et[tt.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${et[tt.PRERELEASEIDENTIFIERLOOSE]})*))`);St("BUILDIDENTIFIER","[0-9A-Za-z-]+");St("BUILD",`(?:\\+(${et[tt.BUILDIDENTIFIER]}(?:\\.${et[tt.BUILDIDENTIFIER]})*))`);St("FULLPLAIN",`v?${et[tt.MAINVERSION]}${et[tt.PRERELEASE]}?${et[tt.BUILD]}?`);St("FULL",`^${et[tt.FULLPLAIN]}$`);St("LOOSEPLAIN",`[v=\\s]*${et[tt.MAINVERSIONLOOSE]}${et[tt.PRERELEASELOOSE]}?${et[tt.BUILD]}?`);St("LOOSE",`^${et[tt.LOOSEPLAIN]}$`);St("GTLT","((?:<|>)?=?)");St("XRANGEIDENTIFIERLOOSE",`${et[tt.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);St("XRANGEIDENTIFIER",`${et[tt.NUMERICIDENTIFIER]}|x|X|\\*`);St("XRANGEPLAIN",`[v=\\s]*(${et[tt.XRANGEIDENTIFIER]})(?:\\.(${et[tt.XRANGEIDENTIFIER]})(?:\\.(${et[tt.XRANGEIDENTIFIER]})(?:${et[tt.PRERELEASE]})?${et[tt.BUILD]}?)?)?`);St("XRANGEPLAINLOOSE",`[v=\\s]*(${et[tt.XRANGEIDENTIFIERLOOSE]})(?:\\.(${et[tt.XRANGEIDENTIFIERLOOSE]})(?:\\.(${et[tt.XRANGEIDENTIFIERLOOSE]})(?:${et[tt.PRERELEASELOOSE]})?${et[tt.BUILD]}?)?)?`);St("XRANGE",`^${et[tt.GTLT]}\\s*${et[tt.XRANGEPLAIN]}$`);St("XRANGELOOSE",`^${et[tt.GTLT]}\\s*${et[tt.XRANGEPLAINLOOSE]}$`);St("COERCE",`(^|[^\\d])(\\d{1,${dv}})(?:\\.(\\d{1,${dv}}))?(?:\\.(\\d{1,${dv}}))?(?:$|[^\\d])`);St("COERCERTL",et[tt.COERCE],!0);St("LONETILDE","(?:~>?)");St("TILDETRIM",`(\\s*)${et[tt.LONETILDE]}\\s+`,!0);NA.tildeTrimReplace="$1~";St("TILDE",`^${et[tt.LONETILDE]}${et[tt.XRANGEPLAIN]}$`);St("TILDELOOSE",`^${et[tt.LONETILDE]}${et[tt.XRANGEPLAINLOOSE]}$`);St("LONECARET","(?:\\^)");St("CARETTRIM",`(\\s*)${et[tt.LONECARET]}\\s+`,!0);NA.caretTrimReplace="$1^";St("CARET",`^${et[tt.LONECARET]}${et[tt.XRANGEPLAIN]}$`);St("CARETLOOSE",`^${et[tt.LONECARET]}${et[tt.XRANGEPLAINLOOSE]}$`);St("COMPARATORLOOSE",`^${et[tt.GTLT]}\\s*(${et[tt.LOOSEPLAIN]})$|^$`);St("COMPARATOR",`^${et[tt.GTLT]}\\s*(${et[tt.FULLPLAIN]})$|^$`);St("COMPARATORTRIM",`(\\s*)${et[tt.GTLT]}\\s*(${et[tt.LOOSEPLAIN]}|${et[tt.XRANGEPLAIN]})`,!0);NA.comparatorTrimReplace="$1$2$3";St("HYPHENRANGE",`^\\s*(${et[tt.XRANGEPLAIN]})\\s+-\\s+(${et[tt.XRANGEPLAIN]})\\s*$`);St("HYPHENRANGELOOSE",`^\\s*(${et[tt.XRANGEPLAINLOOSE]})\\s+-\\s+(${et[tt.XRANGEPLAINLOOSE]})\\s*$`);St("STAR","(<|>)?=?\\s*\\*");St("GTE0","^\\s*>=\\s*0.0.0\\s*$");St("GTE0PRE","^\\s*>=\\s*0.0.0-0\\s*$")});var hd=w((f$e,XH)=>{var ICe=["includePrerelease","loose","rtl"],yCe=r=>r?typeof r!="object"?{loose:!0}:ICe.filter(e=>r[e]).reduce((e,t)=>(e[t]=!0,e),{}):{};XH.exports=yCe});var MI=w((h$e,$H)=>{var ZH=/^[0-9]+$/,_H=(r,e)=>{let t=ZH.test(r),i=ZH.test(e);return t&&i&&(r=+r,e=+e),r===e?0:t&&!i?-1:i&&!t?1:r_H(e,r);$H.exports={compareIdentifiers:_H,rcompareIdentifiers:wCe}});var Li=w((p$e,iG)=>{var OI=fd(),{MAX_LENGTH:eG,MAX_SAFE_INTEGER:KI}=gd(),{re:tG,t:rG}=uc(),BCe=hd(),{compareIdentifiers:pd}=MI(),Yn=class{constructor(e,t){if(t=BCe(t),e instanceof Yn){if(e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease)return e;e=e.version}else if(typeof e!="string")throw new TypeError(`Invalid Version: ${e}`);if(e.length>eG)throw new TypeError(`version is longer than ${eG} characters`);OI("SemVer",e,t),this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease;let i=e.trim().match(t.loose?tG[rG.LOOSE]:tG[rG.FULL]);if(!i)throw new TypeError(`Invalid Version: ${e}`);if(this.raw=e,this.major=+i[1],this.minor=+i[2],this.patch=+i[3],this.major>KI||this.major<0)throw new TypeError("Invalid major version");if(this.minor>KI||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>KI||this.patch<0)throw new TypeError("Invalid patch version");i[4]?this.prerelease=i[4].split(".").map(n=>{if(/^[0-9]+$/.test(n)){let s=+n;if(s>=0&&s=0;)typeof this.prerelease[i]=="number"&&(this.prerelease[i]++,i=-2);i===-1&&this.prerelease.push(0)}t&&(this.prerelease[0]===t?isNaN(this.prerelease[1])&&(this.prerelease=[t,0]):this.prerelease=[t,0]);break;default:throw new Error(`invalid increment argument: ${e}`)}return this.format(),this.raw=this.version,this}};iG.exports=Yn});var gc=w((d$e,aG)=>{var{MAX_LENGTH:bCe}=gd(),{re:nG,t:sG}=uc(),oG=Li(),QCe=hd(),SCe=(r,e)=>{if(e=QCe(e),r instanceof oG)return r;if(typeof r!="string"||r.length>bCe||!(e.loose?nG[sG.LOOSE]:nG[sG.FULL]).test(r))return null;try{return new oG(r,e)}catch{return null}};aG.exports=SCe});var lG=w((C$e,AG)=>{var vCe=gc(),xCe=(r,e)=>{let t=vCe(r,e);return t?t.version:null};AG.exports=xCe});var uG=w((m$e,cG)=>{var PCe=gc(),DCe=(r,e)=>{let t=PCe(r.trim().replace(/^[=v]+/,""),e);return t?t.version:null};cG.exports=DCe});var fG=w((E$e,gG)=>{var kCe=Li(),RCe=(r,e,t,i)=>{typeof t=="string"&&(i=t,t=void 0);try{return new kCe(r,t).inc(e,i).version}catch{return null}};gG.exports=RCe});var cs=w((I$e,pG)=>{var hG=Li(),FCe=(r,e,t)=>new hG(r,t).compare(new hG(e,t));pG.exports=FCe});var UI=w((y$e,dG)=>{var NCe=cs(),TCe=(r,e,t)=>NCe(r,e,t)===0;dG.exports=TCe});var EG=w((w$e,mG)=>{var CG=gc(),LCe=UI(),MCe=(r,e)=>{if(LCe(r,e))return null;{let t=CG(r),i=CG(e),n=t.prerelease.length||i.prerelease.length,s=n?"pre":"",o=n?"prerelease":"";for(let a in t)if((a==="major"||a==="minor"||a==="patch")&&t[a]!==i[a])return s+a;return o}};mG.exports=MCe});var yG=w((B$e,IG)=>{var OCe=Li(),KCe=(r,e)=>new OCe(r,e).major;IG.exports=KCe});var BG=w((b$e,wG)=>{var UCe=Li(),HCe=(r,e)=>new UCe(r,e).minor;wG.exports=HCe});var QG=w((Q$e,bG)=>{var GCe=Li(),YCe=(r,e)=>new GCe(r,e).patch;bG.exports=YCe});var vG=w((S$e,SG)=>{var jCe=gc(),qCe=(r,e)=>{let t=jCe(r,e);return t&&t.prerelease.length?t.prerelease:null};SG.exports=qCe});var PG=w((v$e,xG)=>{var JCe=cs(),WCe=(r,e,t)=>JCe(e,r,t);xG.exports=WCe});var kG=w((x$e,DG)=>{var zCe=cs(),VCe=(r,e)=>zCe(r,e,!0);DG.exports=VCe});var HI=w((P$e,FG)=>{var RG=Li(),XCe=(r,e,t)=>{let i=new RG(r,t),n=new RG(e,t);return i.compare(n)||i.compareBuild(n)};FG.exports=XCe});var TG=w((D$e,NG)=>{var ZCe=HI(),_Ce=(r,e)=>r.sort((t,i)=>ZCe(t,i,e));NG.exports=_Ce});var MG=w((k$e,LG)=>{var $Ce=HI(),eme=(r,e)=>r.sort((t,i)=>$Ce(i,t,e));LG.exports=eme});var dd=w((R$e,OG)=>{var tme=cs(),rme=(r,e,t)=>tme(r,e,t)>0;OG.exports=rme});var GI=w((F$e,KG)=>{var ime=cs(),nme=(r,e,t)=>ime(r,e,t)<0;KG.exports=nme});var Cv=w((N$e,UG)=>{var sme=cs(),ome=(r,e,t)=>sme(r,e,t)!==0;UG.exports=ome});var YI=w((T$e,HG)=>{var ame=cs(),Ame=(r,e,t)=>ame(r,e,t)>=0;HG.exports=Ame});var jI=w((L$e,GG)=>{var lme=cs(),cme=(r,e,t)=>lme(r,e,t)<=0;GG.exports=cme});var mv=w((M$e,YG)=>{var ume=UI(),gme=Cv(),fme=dd(),hme=YI(),pme=GI(),dme=jI(),Cme=(r,e,t,i)=>{switch(e){case"===":return typeof r=="object"&&(r=r.version),typeof t=="object"&&(t=t.version),r===t;case"!==":return typeof r=="object"&&(r=r.version),typeof t=="object"&&(t=t.version),r!==t;case"":case"=":case"==":return ume(r,t,i);case"!=":return gme(r,t,i);case">":return fme(r,t,i);case">=":return hme(r,t,i);case"<":return pme(r,t,i);case"<=":return dme(r,t,i);default:throw new TypeError(`Invalid operator: ${e}`)}};YG.exports=Cme});var qG=w((O$e,jG)=>{var mme=Li(),Eme=gc(),{re:qI,t:JI}=uc(),Ime=(r,e)=>{if(r instanceof mme)return r;if(typeof r=="number"&&(r=String(r)),typeof r!="string")return null;e=e||{};let t=null;if(!e.rtl)t=r.match(qI[JI.COERCE]);else{let i;for(;(i=qI[JI.COERCERTL].exec(r))&&(!t||t.index+t[0].length!==r.length);)(!t||i.index+i[0].length!==t.index+t[0].length)&&(t=i),qI[JI.COERCERTL].lastIndex=i.index+i[1].length+i[2].length;qI[JI.COERCERTL].lastIndex=-1}return t===null?null:Eme(`${t[2]}.${t[3]||"0"}.${t[4]||"0"}`,e)};jG.exports=Ime});var WG=w((K$e,JG)=>{"use strict";JG.exports=function(r){r.prototype[Symbol.iterator]=function*(){for(let e=this.head;e;e=e.next)yield e.value}}});var WI=w((U$e,zG)=>{"use strict";zG.exports=Ht;Ht.Node=fc;Ht.create=Ht;function Ht(r){var e=this;if(e instanceof Ht||(e=new Ht),e.tail=null,e.head=null,e.length=0,r&&typeof r.forEach=="function")r.forEach(function(n){e.push(n)});else if(arguments.length>0)for(var t=0,i=arguments.length;t1)t=e;else if(this.head)i=this.head.next,t=this.head.value;else throw new TypeError("Reduce of empty list with no initial value");for(var n=0;i!==null;n++)t=r(t,i.value,n),i=i.next;return t};Ht.prototype.reduceReverse=function(r,e){var t,i=this.tail;if(arguments.length>1)t=e;else if(this.tail)i=this.tail.prev,t=this.tail.value;else throw new TypeError("Reduce of empty list with no initial value");for(var n=this.length-1;i!==null;n--)t=r(t,i.value,n),i=i.prev;return t};Ht.prototype.toArray=function(){for(var r=new Array(this.length),e=0,t=this.head;t!==null;e++)r[e]=t.value,t=t.next;return r};Ht.prototype.toArrayReverse=function(){for(var r=new Array(this.length),e=0,t=this.tail;t!==null;e++)r[e]=t.value,t=t.prev;return r};Ht.prototype.slice=function(r,e){e=e||this.length,e<0&&(e+=this.length),r=r||0,r<0&&(r+=this.length);var t=new Ht;if(ethis.length&&(e=this.length);for(var i=0,n=this.head;n!==null&&ithis.length&&(e=this.length);for(var i=this.length,n=this.tail;n!==null&&i>e;i--)n=n.prev;for(;n!==null&&i>r;i--,n=n.prev)t.push(n.value);return t};Ht.prototype.splice=function(r,e,...t){r>this.length&&(r=this.length-1),r<0&&(r=this.length+r);for(var i=0,n=this.head;n!==null&&i{"use strict";var bme=WI(),hc=Symbol("max"),va=Symbol("length"),Wg=Symbol("lengthCalculator"),md=Symbol("allowStale"),pc=Symbol("maxAge"),Sa=Symbol("dispose"),VG=Symbol("noDisposeOnSet"),di=Symbol("lruList"),Zs=Symbol("cache"),ZG=Symbol("updateAgeOnGet"),Ev=()=>1,yv=class{constructor(e){if(typeof e=="number"&&(e={max:e}),e||(e={}),e.max&&(typeof e.max!="number"||e.max<0))throw new TypeError("max must be a non-negative number");let t=this[hc]=e.max||1/0,i=e.length||Ev;if(this[Wg]=typeof i!="function"?Ev:i,this[md]=e.stale||!1,e.maxAge&&typeof e.maxAge!="number")throw new TypeError("maxAge must be a number");this[pc]=e.maxAge||0,this[Sa]=e.dispose,this[VG]=e.noDisposeOnSet||!1,this[ZG]=e.updateAgeOnGet||!1,this.reset()}set max(e){if(typeof e!="number"||e<0)throw new TypeError("max must be a non-negative number");this[hc]=e||1/0,Cd(this)}get max(){return this[hc]}set allowStale(e){this[md]=!!e}get allowStale(){return this[md]}set maxAge(e){if(typeof e!="number")throw new TypeError("maxAge must be a non-negative number");this[pc]=e,Cd(this)}get maxAge(){return this[pc]}set lengthCalculator(e){typeof e!="function"&&(e=Ev),e!==this[Wg]&&(this[Wg]=e,this[va]=0,this[di].forEach(t=>{t.length=this[Wg](t.value,t.key),this[va]+=t.length})),Cd(this)}get lengthCalculator(){return this[Wg]}get length(){return this[va]}get itemCount(){return this[di].length}rforEach(e,t){t=t||this;for(let i=this[di].tail;i!==null;){let n=i.prev;XG(this,e,i,t),i=n}}forEach(e,t){t=t||this;for(let i=this[di].head;i!==null;){let n=i.next;XG(this,e,i,t),i=n}}keys(){return this[di].toArray().map(e=>e.key)}values(){return this[di].toArray().map(e=>e.value)}reset(){this[Sa]&&this[di]&&this[di].length&&this[di].forEach(e=>this[Sa](e.key,e.value)),this[Zs]=new Map,this[di]=new bme,this[va]=0}dump(){return this[di].map(e=>zI(this,e)?!1:{k:e.key,v:e.value,e:e.now+(e.maxAge||0)}).toArray().filter(e=>e)}dumpLru(){return this[di]}set(e,t,i){if(i=i||this[pc],i&&typeof i!="number")throw new TypeError("maxAge must be a number");let n=i?Date.now():0,s=this[Wg](t,e);if(this[Zs].has(e)){if(s>this[hc])return zg(this,this[Zs].get(e)),!1;let l=this[Zs].get(e).value;return this[Sa]&&(this[VG]||this[Sa](e,l.value)),l.now=n,l.maxAge=i,l.value=t,this[va]+=s-l.length,l.length=s,this.get(e),Cd(this),!0}let o=new wv(e,t,s,n,i);return o.length>this[hc]?(this[Sa]&&this[Sa](e,t),!1):(this[va]+=o.length,this[di].unshift(o),this[Zs].set(e,this[di].head),Cd(this),!0)}has(e){if(!this[Zs].has(e))return!1;let t=this[Zs].get(e).value;return!zI(this,t)}get(e){return Iv(this,e,!0)}peek(e){return Iv(this,e,!1)}pop(){let e=this[di].tail;return e?(zg(this,e),e.value):null}del(e){zg(this,this[Zs].get(e))}load(e){this.reset();let t=Date.now();for(let i=e.length-1;i>=0;i--){let n=e[i],s=n.e||0;if(s===0)this.set(n.k,n.v);else{let o=s-t;o>0&&this.set(n.k,n.v,o)}}}prune(){this[Zs].forEach((e,t)=>Iv(this,t,!1))}},Iv=(r,e,t)=>{let i=r[Zs].get(e);if(i){let n=i.value;if(zI(r,n)){if(zg(r,i),!r[md])return}else t&&(r[ZG]&&(i.value.now=Date.now()),r[di].unshiftNode(i));return n.value}},zI=(r,e)=>{if(!e||!e.maxAge&&!r[pc])return!1;let t=Date.now()-e.now;return e.maxAge?t>e.maxAge:r[pc]&&t>r[pc]},Cd=r=>{if(r[va]>r[hc])for(let e=r[di].tail;r[va]>r[hc]&&e!==null;){let t=e.prev;zg(r,e),e=t}},zg=(r,e)=>{if(e){let t=e.value;r[Sa]&&r[Sa](t.key,t.value),r[va]-=t.length,r[Zs].delete(t.key),r[di].removeNode(e)}},wv=class{constructor(e,t,i,n,s){this.key=e,this.value=t,this.length=i,this.now=n,this.maxAge=s||0}},XG=(r,e,t,i)=>{let n=t.value;zI(r,n)&&(zg(r,t),r[md]||(n=void 0)),n&&e.call(i,n.value,n.key,r)};_G.exports=yv});var us=w((G$e,iY)=>{var dc=class{constructor(e,t){if(t=Sme(t),e instanceof dc)return e.loose===!!t.loose&&e.includePrerelease===!!t.includePrerelease?e:new dc(e.raw,t);if(e instanceof Bv)return this.raw=e.value,this.set=[[e]],this.format(),this;if(this.options=t,this.loose=!!t.loose,this.includePrerelease=!!t.includePrerelease,this.raw=e,this.set=e.split(/\s*\|\|\s*/).map(i=>this.parseRange(i.trim())).filter(i=>i.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${e}`);if(this.set.length>1){let i=this.set[0];if(this.set=this.set.filter(n=>!tY(n[0])),this.set.length===0)this.set=[i];else if(this.set.length>1){for(let n of this.set)if(n.length===1&&kme(n[0])){this.set=[n];break}}}this.format()}format(){return this.range=this.set.map(e=>e.join(" ").trim()).join("||").trim(),this.range}toString(){return this.range}parseRange(e){e=e.trim();let i=`parseRange:${Object.keys(this.options).join(",")}:${e}`,n=eY.get(i);if(n)return n;let s=this.options.loose,o=s?Mi[bi.HYPHENRANGELOOSE]:Mi[bi.HYPHENRANGE];e=e.replace(o,Hme(this.options.includePrerelease)),Hr("hyphen replace",e),e=e.replace(Mi[bi.COMPARATORTRIM],xme),Hr("comparator trim",e,Mi[bi.COMPARATORTRIM]),e=e.replace(Mi[bi.TILDETRIM],Pme),e=e.replace(Mi[bi.CARETTRIM],Dme),e=e.split(/\s+/).join(" ");let a=s?Mi[bi.COMPARATORLOOSE]:Mi[bi.COMPARATOR],l=e.split(" ").map(f=>Rme(f,this.options)).join(" ").split(/\s+/).map(f=>Ume(f,this.options)).filter(this.options.loose?f=>!!f.match(a):()=>!0).map(f=>new Bv(f,this.options)),c=l.length,u=new Map;for(let f of l){if(tY(f))return[f];u.set(f.value,f)}u.size>1&&u.has("")&&u.delete("");let g=[...u.values()];return eY.set(i,g),g}intersects(e,t){if(!(e instanceof dc))throw new TypeError("a Range is required");return this.set.some(i=>rY(i,t)&&e.set.some(n=>rY(n,t)&&i.every(s=>n.every(o=>s.intersects(o,t)))))}test(e){if(!e)return!1;if(typeof e=="string")try{e=new vme(e,this.options)}catch{return!1}for(let t=0;tr.value==="<0.0.0-0",kme=r=>r.value==="",rY=(r,e)=>{let t=!0,i=r.slice(),n=i.pop();for(;t&&i.length;)t=i.every(s=>n.intersects(s,e)),n=i.pop();return t},Rme=(r,e)=>(Hr("comp",r,e),r=Tme(r,e),Hr("caret",r),r=Fme(r,e),Hr("tildes",r),r=Mme(r,e),Hr("xrange",r),r=Kme(r,e),Hr("stars",r),r),$i=r=>!r||r.toLowerCase()==="x"||r==="*",Fme=(r,e)=>r.trim().split(/\s+/).map(t=>Nme(t,e)).join(" "),Nme=(r,e)=>{let t=e.loose?Mi[bi.TILDELOOSE]:Mi[bi.TILDE];return r.replace(t,(i,n,s,o,a)=>{Hr("tilde",r,i,n,s,o,a);let l;return $i(n)?l="":$i(s)?l=`>=${n}.0.0 <${+n+1}.0.0-0`:$i(o)?l=`>=${n}.${s}.0 <${n}.${+s+1}.0-0`:a?(Hr("replaceTilde pr",a),l=`>=${n}.${s}.${o}-${a} <${n}.${+s+1}.0-0`):l=`>=${n}.${s}.${o} <${n}.${+s+1}.0-0`,Hr("tilde return",l),l})},Tme=(r,e)=>r.trim().split(/\s+/).map(t=>Lme(t,e)).join(" "),Lme=(r,e)=>{Hr("caret",r,e);let t=e.loose?Mi[bi.CARETLOOSE]:Mi[bi.CARET],i=e.includePrerelease?"-0":"";return r.replace(t,(n,s,o,a,l)=>{Hr("caret",r,n,s,o,a,l);let c;return $i(s)?c="":$i(o)?c=`>=${s}.0.0${i} <${+s+1}.0.0-0`:$i(a)?s==="0"?c=`>=${s}.${o}.0${i} <${s}.${+o+1}.0-0`:c=`>=${s}.${o}.0${i} <${+s+1}.0.0-0`:l?(Hr("replaceCaret pr",l),s==="0"?o==="0"?c=`>=${s}.${o}.${a}-${l} <${s}.${o}.${+a+1}-0`:c=`>=${s}.${o}.${a}-${l} <${s}.${+o+1}.0-0`:c=`>=${s}.${o}.${a}-${l} <${+s+1}.0.0-0`):(Hr("no pr"),s==="0"?o==="0"?c=`>=${s}.${o}.${a}${i} <${s}.${o}.${+a+1}-0`:c=`>=${s}.${o}.${a}${i} <${s}.${+o+1}.0-0`:c=`>=${s}.${o}.${a} <${+s+1}.0.0-0`),Hr("caret return",c),c})},Mme=(r,e)=>(Hr("replaceXRanges",r,e),r.split(/\s+/).map(t=>Ome(t,e)).join(" ")),Ome=(r,e)=>{r=r.trim();let t=e.loose?Mi[bi.XRANGELOOSE]:Mi[bi.XRANGE];return r.replace(t,(i,n,s,o,a,l)=>{Hr("xRange",r,i,n,s,o,a,l);let c=$i(s),u=c||$i(o),g=u||$i(a),f=g;return n==="="&&f&&(n=""),l=e.includePrerelease?"-0":"",c?n===">"||n==="<"?i="<0.0.0-0":i="*":n&&f?(u&&(o=0),a=0,n===">"?(n=">=",u?(s=+s+1,o=0,a=0):(o=+o+1,a=0)):n==="<="&&(n="<",u?s=+s+1:o=+o+1),n==="<"&&(l="-0"),i=`${n+s}.${o}.${a}${l}`):u?i=`>=${s}.0.0${l} <${+s+1}.0.0-0`:g&&(i=`>=${s}.${o}.0${l} <${s}.${+o+1}.0-0`),Hr("xRange return",i),i})},Kme=(r,e)=>(Hr("replaceStars",r,e),r.trim().replace(Mi[bi.STAR],"")),Ume=(r,e)=>(Hr("replaceGTE0",r,e),r.trim().replace(Mi[e.includePrerelease?bi.GTE0PRE:bi.GTE0],"")),Hme=r=>(e,t,i,n,s,o,a,l,c,u,g,f,h)=>($i(i)?t="":$i(n)?t=`>=${i}.0.0${r?"-0":""}`:$i(s)?t=`>=${i}.${n}.0${r?"-0":""}`:o?t=`>=${t}`:t=`>=${t}${r?"-0":""}`,$i(c)?l="":$i(u)?l=`<${+c+1}.0.0-0`:$i(g)?l=`<${c}.${+u+1}.0-0`:f?l=`<=${c}.${u}.${g}-${f}`:r?l=`<${c}.${u}.${+g+1}-0`:l=`<=${l}`,`${t} ${l}`.trim()),Gme=(r,e,t)=>{for(let i=0;i0){let n=r[i].semver;if(n.major===e.major&&n.minor===e.minor&&n.patch===e.patch)return!0}return!1}return!0}});var Ed=w((Y$e,AY)=>{var Id=Symbol("SemVer ANY"),Vg=class{static get ANY(){return Id}constructor(e,t){if(t=Yme(t),e instanceof Vg){if(e.loose===!!t.loose)return e;e=e.value}Qv("comparator",e,t),this.options=t,this.loose=!!t.loose,this.parse(e),this.semver===Id?this.value="":this.value=this.operator+this.semver.version,Qv("comp",this)}parse(e){let t=this.options.loose?nY[sY.COMPARATORLOOSE]:nY[sY.COMPARATOR],i=e.match(t);if(!i)throw new TypeError(`Invalid comparator: ${e}`);this.operator=i[1]!==void 0?i[1]:"",this.operator==="="&&(this.operator=""),i[2]?this.semver=new oY(i[2],this.options.loose):this.semver=Id}toString(){return this.value}test(e){if(Qv("Comparator.test",e,this.options.loose),this.semver===Id||e===Id)return!0;if(typeof e=="string")try{e=new oY(e,this.options)}catch{return!1}return bv(e,this.operator,this.semver,this.options)}intersects(e,t){if(!(e instanceof Vg))throw new TypeError("a Comparator is required");if((!t||typeof t!="object")&&(t={loose:!!t,includePrerelease:!1}),this.operator==="")return this.value===""?!0:new aY(e.value,t).test(this.value);if(e.operator==="")return e.value===""?!0:new aY(this.value,t).test(e.semver);let i=(this.operator===">="||this.operator===">")&&(e.operator===">="||e.operator===">"),n=(this.operator==="<="||this.operator==="<")&&(e.operator==="<="||e.operator==="<"),s=this.semver.version===e.semver.version,o=(this.operator===">="||this.operator==="<=")&&(e.operator===">="||e.operator==="<="),a=bv(this.semver,"<",e.semver,t)&&(this.operator===">="||this.operator===">")&&(e.operator==="<="||e.operator==="<"),l=bv(this.semver,">",e.semver,t)&&(this.operator==="<="||this.operator==="<")&&(e.operator===">="||e.operator===">");return i||n||s&&o||a||l}};AY.exports=Vg;var Yme=hd(),{re:nY,t:sY}=uc(),bv=mv(),Qv=fd(),oY=Li(),aY=us()});var yd=w((j$e,lY)=>{var jme=us(),qme=(r,e,t)=>{try{e=new jme(e,t)}catch{return!1}return e.test(r)};lY.exports=qme});var uY=w((q$e,cY)=>{var Jme=us(),Wme=(r,e)=>new Jme(r,e).set.map(t=>t.map(i=>i.value).join(" ").trim().split(" "));cY.exports=Wme});var fY=w((J$e,gY)=>{var zme=Li(),Vme=us(),Xme=(r,e,t)=>{let i=null,n=null,s=null;try{s=new Vme(e,t)}catch{return null}return r.forEach(o=>{s.test(o)&&(!i||n.compare(o)===-1)&&(i=o,n=new zme(i,t))}),i};gY.exports=Xme});var pY=w((W$e,hY)=>{var Zme=Li(),_me=us(),$me=(r,e,t)=>{let i=null,n=null,s=null;try{s=new _me(e,t)}catch{return null}return r.forEach(o=>{s.test(o)&&(!i||n.compare(o)===1)&&(i=o,n=new Zme(i,t))}),i};hY.exports=$me});var mY=w((z$e,CY)=>{var Sv=Li(),eEe=us(),dY=dd(),tEe=(r,e)=>{r=new eEe(r,e);let t=new Sv("0.0.0");if(r.test(t)||(t=new Sv("0.0.0-0"),r.test(t)))return t;t=null;for(let i=0;i{let a=new Sv(o.semver.version);switch(o.operator){case">":a.prerelease.length===0?a.patch++:a.prerelease.push(0),a.raw=a.format();case"":case">=":(!s||dY(a,s))&&(s=a);break;case"<":case"<=":break;default:throw new Error(`Unexpected operation: ${o.operator}`)}}),s&&(!t||dY(t,s))&&(t=s)}return t&&r.test(t)?t:null};CY.exports=tEe});var IY=w((V$e,EY)=>{var rEe=us(),iEe=(r,e)=>{try{return new rEe(r,e).range||"*"}catch{return null}};EY.exports=iEe});var VI=w((X$e,bY)=>{var nEe=Li(),BY=Ed(),{ANY:sEe}=BY,oEe=us(),aEe=yd(),yY=dd(),wY=GI(),AEe=jI(),lEe=YI(),cEe=(r,e,t,i)=>{r=new nEe(r,i),e=new oEe(e,i);let n,s,o,a,l;switch(t){case">":n=yY,s=AEe,o=wY,a=">",l=">=";break;case"<":n=wY,s=lEe,o=yY,a="<",l="<=";break;default:throw new TypeError('Must provide a hilo val of "<" or ">"')}if(aEe(r,e,i))return!1;for(let c=0;c{h.semver===sEe&&(h=new BY(">=0.0.0")),g=g||h,f=f||h,n(h.semver,g.semver,i)?g=h:o(h.semver,f.semver,i)&&(f=h)}),g.operator===a||g.operator===l||(!f.operator||f.operator===a)&&s(r,f.semver))return!1;if(f.operator===l&&o(r,f.semver))return!1}return!0};bY.exports=cEe});var SY=w((Z$e,QY)=>{var uEe=VI(),gEe=(r,e,t)=>uEe(r,e,">",t);QY.exports=gEe});var xY=w((_$e,vY)=>{var fEe=VI(),hEe=(r,e,t)=>fEe(r,e,"<",t);vY.exports=hEe});var kY=w(($$e,DY)=>{var PY=us(),pEe=(r,e,t)=>(r=new PY(r,t),e=new PY(e,t),r.intersects(e));DY.exports=pEe});var FY=w((eet,RY)=>{var dEe=yd(),CEe=cs();RY.exports=(r,e,t)=>{let i=[],n=null,s=null,o=r.sort((u,g)=>CEe(u,g,t));for(let u of o)dEe(u,e,t)?(s=u,n||(n=u)):(s&&i.push([n,s]),s=null,n=null);n&&i.push([n,null]);let a=[];for(let[u,g]of i)u===g?a.push(u):!g&&u===o[0]?a.push("*"):g?u===o[0]?a.push(`<=${g}`):a.push(`${u} - ${g}`):a.push(`>=${u}`);let l=a.join(" || "),c=typeof e.raw=="string"?e.raw:String(e);return l.length{var NY=us(),XI=Ed(),{ANY:vv}=XI,wd=yd(),xv=cs(),mEe=(r,e,t={})=>{if(r===e)return!0;r=new NY(r,t),e=new NY(e,t);let i=!1;e:for(let n of r.set){for(let s of e.set){let o=EEe(n,s,t);if(i=i||o!==null,o)continue e}if(i)return!1}return!0},EEe=(r,e,t)=>{if(r===e)return!0;if(r.length===1&&r[0].semver===vv){if(e.length===1&&e[0].semver===vv)return!0;t.includePrerelease?r=[new XI(">=0.0.0-0")]:r=[new XI(">=0.0.0")]}if(e.length===1&&e[0].semver===vv){if(t.includePrerelease)return!0;e=[new XI(">=0.0.0")]}let i=new Set,n,s;for(let h of r)h.operator===">"||h.operator===">="?n=TY(n,h,t):h.operator==="<"||h.operator==="<="?s=LY(s,h,t):i.add(h.semver);if(i.size>1)return null;let o;if(n&&s){if(o=xv(n.semver,s.semver,t),o>0)return null;if(o===0&&(n.operator!==">="||s.operator!=="<="))return null}for(let h of i){if(n&&!wd(h,String(n),t)||s&&!wd(h,String(s),t))return null;for(let p of e)if(!wd(h,String(p),t))return!1;return!0}let a,l,c,u,g=s&&!t.includePrerelease&&s.semver.prerelease.length?s.semver:!1,f=n&&!t.includePrerelease&&n.semver.prerelease.length?n.semver:!1;g&&g.prerelease.length===1&&s.operator==="<"&&g.prerelease[0]===0&&(g=!1);for(let h of e){if(u=u||h.operator===">"||h.operator===">=",c=c||h.operator==="<"||h.operator==="<=",n){if(f&&h.semver.prerelease&&h.semver.prerelease.length&&h.semver.major===f.major&&h.semver.minor===f.minor&&h.semver.patch===f.patch&&(f=!1),h.operator===">"||h.operator===">="){if(a=TY(n,h,t),a===h&&a!==n)return!1}else if(n.operator===">="&&!wd(n.semver,String(h),t))return!1}if(s){if(g&&h.semver.prerelease&&h.semver.prerelease.length&&h.semver.major===g.major&&h.semver.minor===g.minor&&h.semver.patch===g.patch&&(g=!1),h.operator==="<"||h.operator==="<="){if(l=LY(s,h,t),l===h&&l!==s)return!1}else if(s.operator==="<="&&!wd(s.semver,String(h),t))return!1}if(!h.operator&&(s||n)&&o!==0)return!1}return!(n&&c&&!s&&o!==0||s&&u&&!n&&o!==0||f||g)},TY=(r,e,t)=>{if(!r)return e;let i=xv(r.semver,e.semver,t);return i>0?r:i<0||e.operator===">"&&r.operator===">="?e:r},LY=(r,e,t)=>{if(!r)return e;let i=xv(r.semver,e.semver,t);return i<0?r:i>0||e.operator==="<"&&r.operator==="<="?e:r};MY.exports=mEe});var Xr=w((ret,KY)=>{var Pv=uc();KY.exports={re:Pv.re,src:Pv.src,tokens:Pv.t,SEMVER_SPEC_VERSION:gd().SEMVER_SPEC_VERSION,SemVer:Li(),compareIdentifiers:MI().compareIdentifiers,rcompareIdentifiers:MI().rcompareIdentifiers,parse:gc(),valid:lG(),clean:uG(),inc:fG(),diff:EG(),major:yG(),minor:BG(),patch:QG(),prerelease:vG(),compare:cs(),rcompare:PG(),compareLoose:kG(),compareBuild:HI(),sort:TG(),rsort:MG(),gt:dd(),lt:GI(),eq:UI(),neq:Cv(),gte:YI(),lte:jI(),cmp:mv(),coerce:qG(),Comparator:Ed(),Range:us(),satisfies:yd(),toComparators:uY(),maxSatisfying:fY(),minSatisfying:pY(),minVersion:mY(),validRange:IY(),outside:VI(),gtr:SY(),ltr:xY(),intersects:kY(),simplifyRange:FY(),subset:OY()}});var Dv=w(ZI=>{"use strict";Object.defineProperty(ZI,"__esModule",{value:!0});ZI.VERSION=void 0;ZI.VERSION="9.1.0"});var Gt=w((exports,module)=>{"use strict";var __spreadArray=exports&&exports.__spreadArray||function(r,e,t){if(t||arguments.length===2)for(var i=0,n=e.length,s;i{(function(r,e){typeof define=="function"&&define.amd?define([],e):typeof _I=="object"&&_I.exports?_I.exports=e():r.regexpToAst=e()})(typeof self<"u"?self:UY,function(){function r(){}r.prototype.saveState=function(){return{idx:this.idx,input:this.input,groupIdx:this.groupIdx}},r.prototype.restoreState=function(p){this.idx=p.idx,this.input=p.input,this.groupIdx=p.groupIdx},r.prototype.pattern=function(p){this.idx=0,this.input=p,this.groupIdx=0,this.consumeChar("/");var C=this.disjunction();this.consumeChar("/");for(var y={type:"Flags",loc:{begin:this.idx,end:p.length},global:!1,ignoreCase:!1,multiLine:!1,unicode:!1,sticky:!1};this.isRegExpFlag();)switch(this.popChar()){case"g":o(y,"global");break;case"i":o(y,"ignoreCase");break;case"m":o(y,"multiLine");break;case"u":o(y,"unicode");break;case"y":o(y,"sticky");break}if(this.idx!==this.input.length)throw Error("Redundant input: "+this.input.substring(this.idx));return{type:"Pattern",flags:y,value:C,loc:this.loc(0)}},r.prototype.disjunction=function(){var p=[],C=this.idx;for(p.push(this.alternative());this.peekChar()==="|";)this.consumeChar("|"),p.push(this.alternative());return{type:"Disjunction",value:p,loc:this.loc(C)}},r.prototype.alternative=function(){for(var p=[],C=this.idx;this.isTerm();)p.push(this.term());return{type:"Alternative",value:p,loc:this.loc(C)}},r.prototype.term=function(){return this.isAssertion()?this.assertion():this.atom()},r.prototype.assertion=function(){var p=this.idx;switch(this.popChar()){case"^":return{type:"StartAnchor",loc:this.loc(p)};case"$":return{type:"EndAnchor",loc:this.loc(p)};case"\\":switch(this.popChar()){case"b":return{type:"WordBoundary",loc:this.loc(p)};case"B":return{type:"NonWordBoundary",loc:this.loc(p)}}throw Error("Invalid Assertion Escape");case"(":this.consumeChar("?");var C;switch(this.popChar()){case"=":C="Lookahead";break;case"!":C="NegativeLookahead";break}a(C);var y=this.disjunction();return this.consumeChar(")"),{type:C,value:y,loc:this.loc(p)}}l()},r.prototype.quantifier=function(p){var C,y=this.idx;switch(this.popChar()){case"*":C={atLeast:0,atMost:1/0};break;case"+":C={atLeast:1,atMost:1/0};break;case"?":C={atLeast:0,atMost:1};break;case"{":var B=this.integerIncludingZero();switch(this.popChar()){case"}":C={atLeast:B,atMost:B};break;case",":var v;this.isDigit()?(v=this.integerIncludingZero(),C={atLeast:B,atMost:v}):C={atLeast:B,atMost:1/0},this.consumeChar("}");break}if(p===!0&&C===void 0)return;a(C);break}if(!(p===!0&&C===void 0))return a(C),this.peekChar(0)==="?"?(this.consumeChar("?"),C.greedy=!1):C.greedy=!0,C.type="Quantifier",C.loc=this.loc(y),C},r.prototype.atom=function(){var p,C=this.idx;switch(this.peekChar()){case".":p=this.dotAll();break;case"\\":p=this.atomEscape();break;case"[":p=this.characterClass();break;case"(":p=this.group();break}return p===void 0&&this.isPatternCharacter()&&(p=this.patternCharacter()),a(p),p.loc=this.loc(C),this.isQuantifier()&&(p.quantifier=this.quantifier()),p},r.prototype.dotAll=function(){return this.consumeChar("."),{type:"Set",complement:!0,value:[n(` +`),n("\r"),n("\u2028"),n("\u2029")]}},r.prototype.atomEscape=function(){switch(this.consumeChar("\\"),this.peekChar()){case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":return this.decimalEscapeAtom();case"d":case"D":case"s":case"S":case"w":case"W":return this.characterClassEscape();case"f":case"n":case"r":case"t":case"v":return this.controlEscapeAtom();case"c":return this.controlLetterEscapeAtom();case"0":return this.nulCharacterAtom();case"x":return this.hexEscapeSequenceAtom();case"u":return this.regExpUnicodeEscapeSequenceAtom();default:return this.identityEscapeAtom()}},r.prototype.decimalEscapeAtom=function(){var p=this.positiveInteger();return{type:"GroupBackReference",value:p}},r.prototype.characterClassEscape=function(){var p,C=!1;switch(this.popChar()){case"d":p=u;break;case"D":p=u,C=!0;break;case"s":p=f;break;case"S":p=f,C=!0;break;case"w":p=g;break;case"W":p=g,C=!0;break}return a(p),{type:"Set",value:p,complement:C}},r.prototype.controlEscapeAtom=function(){var p;switch(this.popChar()){case"f":p=n("\f");break;case"n":p=n(` +`);break;case"r":p=n("\r");break;case"t":p=n(" ");break;case"v":p=n("\v");break}return a(p),{type:"Character",value:p}},r.prototype.controlLetterEscapeAtom=function(){this.consumeChar("c");var p=this.popChar();if(/[a-zA-Z]/.test(p)===!1)throw Error("Invalid ");var C=p.toUpperCase().charCodeAt(0)-64;return{type:"Character",value:C}},r.prototype.nulCharacterAtom=function(){return this.consumeChar("0"),{type:"Character",value:n("\0")}},r.prototype.hexEscapeSequenceAtom=function(){return this.consumeChar("x"),this.parseHexDigits(2)},r.prototype.regExpUnicodeEscapeSequenceAtom=function(){return this.consumeChar("u"),this.parseHexDigits(4)},r.prototype.identityEscapeAtom=function(){var p=this.popChar();return{type:"Character",value:n(p)}},r.prototype.classPatternCharacterAtom=function(){switch(this.peekChar()){case` +`:case"\r":case"\u2028":case"\u2029":case"\\":case"]":throw Error("TBD");default:var p=this.popChar();return{type:"Character",value:n(p)}}},r.prototype.characterClass=function(){var p=[],C=!1;for(this.consumeChar("["),this.peekChar(0)==="^"&&(this.consumeChar("^"),C=!0);this.isClassAtom();){var y=this.classAtom(),B=y.type==="Character";if(B&&this.isRangeDash()){this.consumeChar("-");var v=this.classAtom(),D=v.type==="Character";if(D){if(v.value=this.input.length)throw Error("Unexpected end of input");this.idx++},r.prototype.loc=function(p){return{begin:p,end:this.idx}};var e=/[0-9a-fA-F]/,t=/[0-9]/,i=/[1-9]/;function n(p){return p.charCodeAt(0)}function s(p,C){p.length!==void 0?p.forEach(function(y){C.push(y)}):C.push(p)}function o(p,C){if(p[C]===!0)throw"duplicate flag "+C;p[C]=!0}function a(p){if(p===void 0)throw Error("Internal Error - Should never get here!")}function l(){throw Error("Internal Error - Should never get here!")}var c,u=[];for(c=n("0");c<=n("9");c++)u.push(c);var g=[n("_")].concat(u);for(c=n("a");c<=n("z");c++)g.push(c);for(c=n("A");c<=n("Z");c++)g.push(c);var f=[n(" "),n("\f"),n(` +`),n("\r"),n(" "),n("\v"),n(" "),n("\xA0"),n("\u1680"),n("\u2000"),n("\u2001"),n("\u2002"),n("\u2003"),n("\u2004"),n("\u2005"),n("\u2006"),n("\u2007"),n("\u2008"),n("\u2009"),n("\u200A"),n("\u2028"),n("\u2029"),n("\u202F"),n("\u205F"),n("\u3000"),n("\uFEFF")];function h(){}return h.prototype.visitChildren=function(p){for(var C in p){var y=p[C];p.hasOwnProperty(C)&&(y.type!==void 0?this.visit(y):Array.isArray(y)&&y.forEach(function(B){this.visit(B)},this))}},h.prototype.visit=function(p){switch(p.type){case"Pattern":this.visitPattern(p);break;case"Flags":this.visitFlags(p);break;case"Disjunction":this.visitDisjunction(p);break;case"Alternative":this.visitAlternative(p);break;case"StartAnchor":this.visitStartAnchor(p);break;case"EndAnchor":this.visitEndAnchor(p);break;case"WordBoundary":this.visitWordBoundary(p);break;case"NonWordBoundary":this.visitNonWordBoundary(p);break;case"Lookahead":this.visitLookahead(p);break;case"NegativeLookahead":this.visitNegativeLookahead(p);break;case"Character":this.visitCharacter(p);break;case"Set":this.visitSet(p);break;case"Group":this.visitGroup(p);break;case"GroupBackReference":this.visitGroupBackReference(p);break;case"Quantifier":this.visitQuantifier(p);break}this.visitChildren(p)},h.prototype.visitPattern=function(p){},h.prototype.visitFlags=function(p){},h.prototype.visitDisjunction=function(p){},h.prototype.visitAlternative=function(p){},h.prototype.visitStartAnchor=function(p){},h.prototype.visitEndAnchor=function(p){},h.prototype.visitWordBoundary=function(p){},h.prototype.visitNonWordBoundary=function(p){},h.prototype.visitLookahead=function(p){},h.prototype.visitNegativeLookahead=function(p){},h.prototype.visitCharacter=function(p){},h.prototype.visitSet=function(p){},h.prototype.visitGroup=function(p){},h.prototype.visitGroupBackReference=function(p){},h.prototype.visitQuantifier=function(p){},{RegExpParser:r,BaseRegExpVisitor:h,VERSION:"0.5.0"}})});var ty=w(Xg=>{"use strict";Object.defineProperty(Xg,"__esModule",{value:!0});Xg.clearRegExpParserCache=Xg.getRegExpAst=void 0;var IEe=$I(),ey={},yEe=new IEe.RegExpParser;function wEe(r){var e=r.toString();if(ey.hasOwnProperty(e))return ey[e];var t=yEe.pattern(e);return ey[e]=t,t}Xg.getRegExpAst=wEe;function BEe(){ey={}}Xg.clearRegExpParserCache=BEe});var qY=w(Cn=>{"use strict";var bEe=Cn&&Cn.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Cn,"__esModule",{value:!0});Cn.canMatchCharCode=Cn.firstCharOptimizedIndices=Cn.getOptimizedStartCodesIndices=Cn.failedOptimizationPrefixMsg=void 0;var GY=$I(),gs=Gt(),YY=ty(),xa=Rv(),jY="Complement Sets are not supported for first char optimization";Cn.failedOptimizationPrefixMsg=`Unable to use "first char" lexer optimizations: +`;function QEe(r,e){e===void 0&&(e=!1);try{var t=(0,YY.getRegExpAst)(r),i=iy(t.value,{},t.flags.ignoreCase);return i}catch(s){if(s.message===jY)e&&(0,gs.PRINT_WARNING)(""+Cn.failedOptimizationPrefixMsg+(" Unable to optimize: < "+r.toString()+` > +`)+` Complement Sets cannot be automatically optimized. + This will disable the lexer's first char optimizations. + See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#COMPLEMENT for details.`);else{var n="";e&&(n=` + This will disable the lexer's first char optimizations. + See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#REGEXP_PARSING for details.`),(0,gs.PRINT_ERROR)(Cn.failedOptimizationPrefixMsg+` +`+(" Failed parsing: < "+r.toString()+` > +`)+(" Using the regexp-to-ast library version: "+GY.VERSION+` +`)+" Please open an issue at: https://github.com/bd82/regexp-to-ast/issues"+n)}}return[]}Cn.getOptimizedStartCodesIndices=QEe;function iy(r,e,t){switch(r.type){case"Disjunction":for(var i=0;i=xa.minOptimizationVal)for(var f=u.from>=xa.minOptimizationVal?u.from:xa.minOptimizationVal,h=u.to,p=(0,xa.charCodeToOptimizedIndex)(f),C=(0,xa.charCodeToOptimizedIndex)(h),y=p;y<=C;y++)e[y]=y}}});break;case"Group":iy(o.value,e,t);break;default:throw Error("Non Exhaustive Match")}var a=o.quantifier!==void 0&&o.quantifier.atLeast===0;if(o.type==="Group"&&kv(o)===!1||o.type!=="Group"&&a===!1)break}break;default:throw Error("non exhaustive match!")}return(0,gs.values)(e)}Cn.firstCharOptimizedIndices=iy;function ry(r,e,t){var i=(0,xa.charCodeToOptimizedIndex)(r);e[i]=i,t===!0&&SEe(r,e)}function SEe(r,e){var t=String.fromCharCode(r),i=t.toUpperCase();if(i!==t){var n=(0,xa.charCodeToOptimizedIndex)(i.charCodeAt(0));e[n]=n}else{var s=t.toLowerCase();if(s!==t){var n=(0,xa.charCodeToOptimizedIndex)(s.charCodeAt(0));e[n]=n}}}function HY(r,e){return(0,gs.find)(r.value,function(t){if(typeof t=="number")return(0,gs.contains)(e,t);var i=t;return(0,gs.find)(e,function(n){return i.from<=n&&n<=i.to})!==void 0})}function kv(r){return r.quantifier&&r.quantifier.atLeast===0?!0:r.value?(0,gs.isArray)(r.value)?(0,gs.every)(r.value,kv):kv(r.value):!1}var vEe=function(r){bEe(e,r);function e(t){var i=r.call(this)||this;return i.targetCharCodes=t,i.found=!1,i}return e.prototype.visitChildren=function(t){if(this.found!==!0){switch(t.type){case"Lookahead":this.visitLookahead(t);return;case"NegativeLookahead":this.visitNegativeLookahead(t);return}r.prototype.visitChildren.call(this,t)}},e.prototype.visitCharacter=function(t){(0,gs.contains)(this.targetCharCodes,t.value)&&(this.found=!0)},e.prototype.visitSet=function(t){t.complement?HY(t,this.targetCharCodes)===void 0&&(this.found=!0):HY(t,this.targetCharCodes)!==void 0&&(this.found=!0)},e}(GY.BaseRegExpVisitor);function xEe(r,e){if(e instanceof RegExp){var t=(0,YY.getRegExpAst)(e),i=new vEe(r);return i.visit(t),i.found}else return(0,gs.find)(e,function(n){return(0,gs.contains)(r,n.charCodeAt(0))})!==void 0}Cn.canMatchCharCode=xEe});var Rv=w(Ve=>{"use strict";var JY=Ve&&Ve.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Ve,"__esModule",{value:!0});Ve.charCodeToOptimizedIndex=Ve.minOptimizationVal=Ve.buildLineBreakIssueMessage=Ve.LineTerminatorOptimizedTester=Ve.isShortPattern=Ve.isCustomPattern=Ve.cloneEmptyGroups=Ve.performWarningRuntimeChecks=Ve.performRuntimeChecks=Ve.addStickyFlag=Ve.addStartOfInput=Ve.findUnreachablePatterns=Ve.findModesThatDoNotExist=Ve.findInvalidGroupType=Ve.findDuplicatePatterns=Ve.findUnsupportedFlags=Ve.findStartOfInputAnchor=Ve.findEmptyMatchRegExps=Ve.findEndOfInputAnchor=Ve.findInvalidPatterns=Ve.findMissingPatterns=Ve.validatePatterns=Ve.analyzeTokenTypes=Ve.enableSticky=Ve.disableSticky=Ve.SUPPORT_STICKY=Ve.MODES=Ve.DEFAULT_MODE=void 0;var WY=$I(),ir=Bd(),xe=Gt(),Zg=qY(),zY=ty(),ko="PATTERN";Ve.DEFAULT_MODE="defaultMode";Ve.MODES="modes";Ve.SUPPORT_STICKY=typeof new RegExp("(?:)").sticky=="boolean";function PEe(){Ve.SUPPORT_STICKY=!1}Ve.disableSticky=PEe;function DEe(){Ve.SUPPORT_STICKY=!0}Ve.enableSticky=DEe;function kEe(r,e){e=(0,xe.defaults)(e,{useSticky:Ve.SUPPORT_STICKY,debug:!1,safeMode:!1,positionTracking:"full",lineTerminatorCharacters:["\r",` +`],tracer:function(v,D){return D()}});var t=e.tracer;t("initCharCodeToOptimizedIndexMap",function(){HEe()});var i;t("Reject Lexer.NA",function(){i=(0,xe.reject)(r,function(v){return v[ko]===ir.Lexer.NA})});var n=!1,s;t("Transform Patterns",function(){n=!1,s=(0,xe.map)(i,function(v){var D=v[ko];if((0,xe.isRegExp)(D)){var T=D.source;return T.length===1&&T!=="^"&&T!=="$"&&T!=="."&&!D.ignoreCase?T:T.length===2&&T[0]==="\\"&&!(0,xe.contains)(["d","D","s","S","t","r","n","t","0","c","b","B","f","v","w","W"],T[1])?T[1]:e.useSticky?Tv(D):Nv(D)}else{if((0,xe.isFunction)(D))return n=!0,{exec:D};if((0,xe.has)(D,"exec"))return n=!0,D;if(typeof D=="string"){if(D.length===1)return D;var H=D.replace(/[\\^$.*+?()[\]{}|]/g,"\\$&"),j=new RegExp(H);return e.useSticky?Tv(j):Nv(j)}else throw Error("non exhaustive match")}})});var o,a,l,c,u;t("misc mapping",function(){o=(0,xe.map)(i,function(v){return v.tokenTypeIdx}),a=(0,xe.map)(i,function(v){var D=v.GROUP;if(D!==ir.Lexer.SKIPPED){if((0,xe.isString)(D))return D;if((0,xe.isUndefined)(D))return!1;throw Error("non exhaustive match")}}),l=(0,xe.map)(i,function(v){var D=v.LONGER_ALT;if(D){var T=(0,xe.isArray)(D)?(0,xe.map)(D,function(H){return(0,xe.indexOf)(i,H)}):[(0,xe.indexOf)(i,D)];return T}}),c=(0,xe.map)(i,function(v){return v.PUSH_MODE}),u=(0,xe.map)(i,function(v){return(0,xe.has)(v,"POP_MODE")})});var g;t("Line Terminator Handling",function(){var v=Aj(e.lineTerminatorCharacters);g=(0,xe.map)(i,function(D){return!1}),e.positionTracking!=="onlyOffset"&&(g=(0,xe.map)(i,function(D){if((0,xe.has)(D,"LINE_BREAKS"))return D.LINE_BREAKS;if(oj(D,v)===!1)return(0,Zg.canMatchCharCode)(v,D.PATTERN)}))});var f,h,p,C;t("Misc Mapping #2",function(){f=(0,xe.map)(i,Mv),h=(0,xe.map)(s,sj),p=(0,xe.reduce)(i,function(v,D){var T=D.GROUP;return(0,xe.isString)(T)&&T!==ir.Lexer.SKIPPED&&(v[T]=[]),v},{}),C=(0,xe.map)(s,function(v,D){return{pattern:s[D],longerAlt:l[D],canLineTerminator:g[D],isCustom:f[D],short:h[D],group:a[D],push:c[D],pop:u[D],tokenTypeIdx:o[D],tokenType:i[D]}})});var y=!0,B=[];return e.safeMode||t("First Char Optimization",function(){B=(0,xe.reduce)(i,function(v,D,T){if(typeof D.PATTERN=="string"){var H=D.PATTERN.charCodeAt(0),j=Lv(H);Fv(v,j,C[T])}else if((0,xe.isArray)(D.START_CHARS_HINT)){var $;(0,xe.forEach)(D.START_CHARS_HINT,function(W){var _=typeof W=="string"?W.charCodeAt(0):W,A=Lv(_);$!==A&&($=A,Fv(v,A,C[T]))})}else if((0,xe.isRegExp)(D.PATTERN))if(D.PATTERN.unicode)y=!1,e.ensureOptimizations&&(0,xe.PRINT_ERROR)(""+Zg.failedOptimizationPrefixMsg+(" Unable to analyze < "+D.PATTERN.toString()+` > pattern. +`)+` The regexp unicode flag is not currently supported by the regexp-to-ast library. + This will disable the lexer's first char optimizations. + For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#UNICODE_OPTIMIZE`);else{var V=(0,Zg.getOptimizedStartCodesIndices)(D.PATTERN,e.ensureOptimizations);(0,xe.isEmpty)(V)&&(y=!1),(0,xe.forEach)(V,function(W){Fv(v,W,C[T])})}else e.ensureOptimizations&&(0,xe.PRINT_ERROR)(""+Zg.failedOptimizationPrefixMsg+(" TokenType: <"+D.name+`> is using a custom token pattern without providing parameter. +`)+` This will disable the lexer's first char optimizations. + For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#CUSTOM_OPTIMIZE`),y=!1;return v},[])}),t("ArrayPacking",function(){B=(0,xe.packArray)(B)}),{emptyGroups:p,patternIdxToConfig:C,charCodeToPatternIdxToConfig:B,hasCustom:n,canBeOptimized:y}}Ve.analyzeTokenTypes=kEe;function REe(r,e){var t=[],i=VY(r);t=t.concat(i.errors);var n=XY(i.valid),s=n.valid;return t=t.concat(n.errors),t=t.concat(FEe(s)),t=t.concat(rj(s)),t=t.concat(ij(s,e)),t=t.concat(nj(s)),t}Ve.validatePatterns=REe;function FEe(r){var e=[],t=(0,xe.filter)(r,function(i){return(0,xe.isRegExp)(i[ko])});return e=e.concat(ZY(t)),e=e.concat($Y(t)),e=e.concat(ej(t)),e=e.concat(tj(t)),e=e.concat(_Y(t)),e}function VY(r){var e=(0,xe.filter)(r,function(n){return!(0,xe.has)(n,ko)}),t=(0,xe.map)(e,function(n){return{message:"Token Type: ->"+n.name+"<- missing static 'PATTERN' property",type:ir.LexerDefinitionErrorType.MISSING_PATTERN,tokenTypes:[n]}}),i=(0,xe.difference)(r,e);return{errors:t,valid:i}}Ve.findMissingPatterns=VY;function XY(r){var e=(0,xe.filter)(r,function(n){var s=n[ko];return!(0,xe.isRegExp)(s)&&!(0,xe.isFunction)(s)&&!(0,xe.has)(s,"exec")&&!(0,xe.isString)(s)}),t=(0,xe.map)(e,function(n){return{message:"Token Type: ->"+n.name+"<- static 'PATTERN' can only be a RegExp, a Function matching the {CustomPatternMatcherFunc} type or an Object matching the {ICustomPattern} interface.",type:ir.LexerDefinitionErrorType.INVALID_PATTERN,tokenTypes:[n]}}),i=(0,xe.difference)(r,e);return{errors:t,valid:i}}Ve.findInvalidPatterns=XY;var NEe=/[^\\][\$]/;function ZY(r){var e=function(n){JY(s,n);function s(){var o=n!==null&&n.apply(this,arguments)||this;return o.found=!1,o}return s.prototype.visitEndAnchor=function(o){this.found=!0},s}(WY.BaseRegExpVisitor),t=(0,xe.filter)(r,function(n){var s=n[ko];try{var o=(0,zY.getRegExpAst)(s),a=new e;return a.visit(o),a.found}catch{return NEe.test(s.source)}}),i=(0,xe.map)(t,function(n){return{message:`Unexpected RegExp Anchor Error: + Token Type: ->`+n.name+`<- static 'PATTERN' cannot contain end of input anchor '$' + See chevrotain.io/docs/guide/resolving_lexer_errors.html#ANCHORS for details.`,type:ir.LexerDefinitionErrorType.EOI_ANCHOR_FOUND,tokenTypes:[n]}});return i}Ve.findEndOfInputAnchor=ZY;function _Y(r){var e=(0,xe.filter)(r,function(i){var n=i[ko];return n.test("")}),t=(0,xe.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'PATTERN' must not match an empty string",type:ir.LexerDefinitionErrorType.EMPTY_MATCH_PATTERN,tokenTypes:[i]}});return t}Ve.findEmptyMatchRegExps=_Y;var TEe=/[^\\[][\^]|^\^/;function $Y(r){var e=function(n){JY(s,n);function s(){var o=n!==null&&n.apply(this,arguments)||this;return o.found=!1,o}return s.prototype.visitStartAnchor=function(o){this.found=!0},s}(WY.BaseRegExpVisitor),t=(0,xe.filter)(r,function(n){var s=n[ko];try{var o=(0,zY.getRegExpAst)(s),a=new e;return a.visit(o),a.found}catch{return TEe.test(s.source)}}),i=(0,xe.map)(t,function(n){return{message:`Unexpected RegExp Anchor Error: + Token Type: ->`+n.name+`<- static 'PATTERN' cannot contain start of input anchor '^' + See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#ANCHORS for details.`,type:ir.LexerDefinitionErrorType.SOI_ANCHOR_FOUND,tokenTypes:[n]}});return i}Ve.findStartOfInputAnchor=$Y;function ej(r){var e=(0,xe.filter)(r,function(i){var n=i[ko];return n instanceof RegExp&&(n.multiline||n.global)}),t=(0,xe.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'PATTERN' may NOT contain global('g') or multiline('m')",type:ir.LexerDefinitionErrorType.UNSUPPORTED_FLAGS_FOUND,tokenTypes:[i]}});return t}Ve.findUnsupportedFlags=ej;function tj(r){var e=[],t=(0,xe.map)(r,function(s){return(0,xe.reduce)(r,function(o,a){return s.PATTERN.source===a.PATTERN.source&&!(0,xe.contains)(e,a)&&a.PATTERN!==ir.Lexer.NA&&(e.push(a),o.push(a)),o},[])});t=(0,xe.compact)(t);var i=(0,xe.filter)(t,function(s){return s.length>1}),n=(0,xe.map)(i,function(s){var o=(0,xe.map)(s,function(l){return l.name}),a=(0,xe.first)(s).PATTERN;return{message:"The same RegExp pattern ->"+a+"<-"+("has been used in all of the following Token Types: "+o.join(", ")+" <-"),type:ir.LexerDefinitionErrorType.DUPLICATE_PATTERNS_FOUND,tokenTypes:s}});return n}Ve.findDuplicatePatterns=tj;function rj(r){var e=(0,xe.filter)(r,function(i){if(!(0,xe.has)(i,"GROUP"))return!1;var n=i.GROUP;return n!==ir.Lexer.SKIPPED&&n!==ir.Lexer.NA&&!(0,xe.isString)(n)}),t=(0,xe.map)(e,function(i){return{message:"Token Type: ->"+i.name+"<- static 'GROUP' can only be Lexer.SKIPPED/Lexer.NA/A String",type:ir.LexerDefinitionErrorType.INVALID_GROUP_TYPE_FOUND,tokenTypes:[i]}});return t}Ve.findInvalidGroupType=rj;function ij(r,e){var t=(0,xe.filter)(r,function(n){return n.PUSH_MODE!==void 0&&!(0,xe.contains)(e,n.PUSH_MODE)}),i=(0,xe.map)(t,function(n){var s="Token Type: ->"+n.name+"<- static 'PUSH_MODE' value cannot refer to a Lexer Mode ->"+n.PUSH_MODE+"<-which does not exist";return{message:s,type:ir.LexerDefinitionErrorType.PUSH_MODE_DOES_NOT_EXIST,tokenTypes:[n]}});return i}Ve.findModesThatDoNotExist=ij;function nj(r){var e=[],t=(0,xe.reduce)(r,function(i,n,s){var o=n.PATTERN;return o===ir.Lexer.NA||((0,xe.isString)(o)?i.push({str:o,idx:s,tokenType:n}):(0,xe.isRegExp)(o)&&MEe(o)&&i.push({str:o.source,idx:s,tokenType:n})),i},[]);return(0,xe.forEach)(r,function(i,n){(0,xe.forEach)(t,function(s){var o=s.str,a=s.idx,l=s.tokenType;if(n"+i.name+"<-")+`in the lexer's definition. +See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#UNREACHABLE`;e.push({message:c,type:ir.LexerDefinitionErrorType.UNREACHABLE_PATTERN,tokenTypes:[i,l]})}})}),e}Ve.findUnreachablePatterns=nj;function LEe(r,e){if((0,xe.isRegExp)(e)){var t=e.exec(r);return t!==null&&t.index===0}else{if((0,xe.isFunction)(e))return e(r,0,[],{});if((0,xe.has)(e,"exec"))return e.exec(r,0,[],{});if(typeof e=="string")return e===r;throw Error("non exhaustive match")}}function MEe(r){var e=[".","\\","[","]","|","^","$","(",")","?","*","+","{"];return(0,xe.find)(e,function(t){return r.source.indexOf(t)!==-1})===void 0}function Nv(r){var e=r.ignoreCase?"i":"";return new RegExp("^(?:"+r.source+")",e)}Ve.addStartOfInput=Nv;function Tv(r){var e=r.ignoreCase?"iy":"y";return new RegExp(""+r.source,e)}Ve.addStickyFlag=Tv;function OEe(r,e,t){var i=[];return(0,xe.has)(r,Ve.DEFAULT_MODE)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+Ve.DEFAULT_MODE+`> property in its definition +`,type:ir.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE}),(0,xe.has)(r,Ve.MODES)||i.push({message:"A MultiMode Lexer cannot be initialized without a <"+Ve.MODES+`> property in its definition +`,type:ir.LexerDefinitionErrorType.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY}),(0,xe.has)(r,Ve.MODES)&&(0,xe.has)(r,Ve.DEFAULT_MODE)&&!(0,xe.has)(r.modes,r.defaultMode)&&i.push({message:"A MultiMode Lexer cannot be initialized with a "+Ve.DEFAULT_MODE+": <"+r.defaultMode+`>which does not exist +`,type:ir.LexerDefinitionErrorType.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST}),(0,xe.has)(r,Ve.MODES)&&(0,xe.forEach)(r.modes,function(n,s){(0,xe.forEach)(n,function(o,a){(0,xe.isUndefined)(o)&&i.push({message:"A Lexer cannot be initialized using an undefined Token Type. Mode:"+("<"+s+"> at index: <"+a+`> +`),type:ir.LexerDefinitionErrorType.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED})})}),i}Ve.performRuntimeChecks=OEe;function KEe(r,e,t){var i=[],n=!1,s=(0,xe.compact)((0,xe.flatten)((0,xe.mapValues)(r.modes,function(l){return l}))),o=(0,xe.reject)(s,function(l){return l[ko]===ir.Lexer.NA}),a=Aj(t);return e&&(0,xe.forEach)(o,function(l){var c=oj(l,a);if(c!==!1){var u=aj(l,c),g={message:u,type:c.issue,tokenType:l};i.push(g)}else(0,xe.has)(l,"LINE_BREAKS")?l.LINE_BREAKS===!0&&(n=!0):(0,Zg.canMatchCharCode)(a,l.PATTERN)&&(n=!0)}),e&&!n&&i.push({message:`Warning: No LINE_BREAKS Found. + This Lexer has been defined to track line and column information, + But none of the Token Types can be identified as matching a line terminator. + See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#LINE_BREAKS + for details.`,type:ir.LexerDefinitionErrorType.NO_LINE_BREAKS_FLAGS}),i}Ve.performWarningRuntimeChecks=KEe;function UEe(r){var e={},t=(0,xe.keys)(r);return(0,xe.forEach)(t,function(i){var n=r[i];if((0,xe.isArray)(n))e[i]=[];else throw Error("non exhaustive match")}),e}Ve.cloneEmptyGroups=UEe;function Mv(r){var e=r.PATTERN;if((0,xe.isRegExp)(e))return!1;if((0,xe.isFunction)(e))return!0;if((0,xe.has)(e,"exec"))return!0;if((0,xe.isString)(e))return!1;throw Error("non exhaustive match")}Ve.isCustomPattern=Mv;function sj(r){return(0,xe.isString)(r)&&r.length===1?r.charCodeAt(0):!1}Ve.isShortPattern=sj;Ve.LineTerminatorOptimizedTester={test:function(r){for(var e=r.length,t=this.lastIndex;t Token Type +`)+(" Root cause: "+e.errMsg+`. +`)+" For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#IDENTIFY_TERMINATOR";if(e.issue===ir.LexerDefinitionErrorType.CUSTOM_LINE_BREAK)return`Warning: A Custom Token Pattern should specify the option. +`+(" The problem is in the <"+r.name+`> Token Type +`)+" For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#CUSTOM_LINE_BREAK";throw Error("non exhaustive match")}Ve.buildLineBreakIssueMessage=aj;function Aj(r){var e=(0,xe.map)(r,function(t){return(0,xe.isString)(t)&&t.length>0?t.charCodeAt(0):t});return e}function Fv(r,e,t){r[e]===void 0?r[e]=[t]:r[e].push(t)}Ve.minOptimizationVal=256;var ny=[];function Lv(r){return r255?255+~~(r/255):r}}});var _g=w(Nt=>{"use strict";Object.defineProperty(Nt,"__esModule",{value:!0});Nt.isTokenType=Nt.hasExtendingTokensTypesMapProperty=Nt.hasExtendingTokensTypesProperty=Nt.hasCategoriesProperty=Nt.hasShortKeyProperty=Nt.singleAssignCategoriesToksMap=Nt.assignCategoriesMapProp=Nt.assignCategoriesTokensProp=Nt.assignTokenDefaultProps=Nt.expandCategories=Nt.augmentTokenTypes=Nt.tokenIdxToClass=Nt.tokenShortNameIdx=Nt.tokenStructuredMatcherNoCategories=Nt.tokenStructuredMatcher=void 0;var Zr=Gt();function GEe(r,e){var t=r.tokenTypeIdx;return t===e.tokenTypeIdx?!0:e.isParent===!0&&e.categoryMatchesMap[t]===!0}Nt.tokenStructuredMatcher=GEe;function YEe(r,e){return r.tokenTypeIdx===e.tokenTypeIdx}Nt.tokenStructuredMatcherNoCategories=YEe;Nt.tokenShortNameIdx=1;Nt.tokenIdxToClass={};function jEe(r){var e=lj(r);cj(e),gj(e),uj(e),(0,Zr.forEach)(e,function(t){t.isParent=t.categoryMatches.length>0})}Nt.augmentTokenTypes=jEe;function lj(r){for(var e=(0,Zr.cloneArr)(r),t=r,i=!0;i;){t=(0,Zr.compact)((0,Zr.flatten)((0,Zr.map)(t,function(s){return s.CATEGORIES})));var n=(0,Zr.difference)(t,e);e=e.concat(n),(0,Zr.isEmpty)(n)?i=!1:t=n}return e}Nt.expandCategories=lj;function cj(r){(0,Zr.forEach)(r,function(e){fj(e)||(Nt.tokenIdxToClass[Nt.tokenShortNameIdx]=e,e.tokenTypeIdx=Nt.tokenShortNameIdx++),Ov(e)&&!(0,Zr.isArray)(e.CATEGORIES)&&(e.CATEGORIES=[e.CATEGORIES]),Ov(e)||(e.CATEGORIES=[]),hj(e)||(e.categoryMatches=[]),pj(e)||(e.categoryMatchesMap={})})}Nt.assignTokenDefaultProps=cj;function uj(r){(0,Zr.forEach)(r,function(e){e.categoryMatches=[],(0,Zr.forEach)(e.categoryMatchesMap,function(t,i){e.categoryMatches.push(Nt.tokenIdxToClass[i].tokenTypeIdx)})})}Nt.assignCategoriesTokensProp=uj;function gj(r){(0,Zr.forEach)(r,function(e){Kv([],e)})}Nt.assignCategoriesMapProp=gj;function Kv(r,e){(0,Zr.forEach)(r,function(t){e.categoryMatchesMap[t.tokenTypeIdx]=!0}),(0,Zr.forEach)(e.CATEGORIES,function(t){var i=r.concat(e);(0,Zr.contains)(i,t)||Kv(i,t)})}Nt.singleAssignCategoriesToksMap=Kv;function fj(r){return(0,Zr.has)(r,"tokenTypeIdx")}Nt.hasShortKeyProperty=fj;function Ov(r){return(0,Zr.has)(r,"CATEGORIES")}Nt.hasCategoriesProperty=Ov;function hj(r){return(0,Zr.has)(r,"categoryMatches")}Nt.hasExtendingTokensTypesProperty=hj;function pj(r){return(0,Zr.has)(r,"categoryMatchesMap")}Nt.hasExtendingTokensTypesMapProperty=pj;function qEe(r){return(0,Zr.has)(r,"tokenTypeIdx")}Nt.isTokenType=qEe});var Uv=w(sy=>{"use strict";Object.defineProperty(sy,"__esModule",{value:!0});sy.defaultLexerErrorProvider=void 0;sy.defaultLexerErrorProvider={buildUnableToPopLexerModeMessage:function(r){return"Unable to pop Lexer Mode after encountering Token ->"+r.image+"<- The Mode Stack is empty"},buildUnexpectedCharactersMessage:function(r,e,t,i,n){return"unexpected character: ->"+r.charAt(e)+"<- at offset: "+e+","+(" skipped "+t+" characters.")}}});var Bd=w(Cc=>{"use strict";Object.defineProperty(Cc,"__esModule",{value:!0});Cc.Lexer=Cc.LexerDefinitionErrorType=void 0;var _s=Rv(),nr=Gt(),JEe=_g(),WEe=Uv(),zEe=ty(),VEe;(function(r){r[r.MISSING_PATTERN=0]="MISSING_PATTERN",r[r.INVALID_PATTERN=1]="INVALID_PATTERN",r[r.EOI_ANCHOR_FOUND=2]="EOI_ANCHOR_FOUND",r[r.UNSUPPORTED_FLAGS_FOUND=3]="UNSUPPORTED_FLAGS_FOUND",r[r.DUPLICATE_PATTERNS_FOUND=4]="DUPLICATE_PATTERNS_FOUND",r[r.INVALID_GROUP_TYPE_FOUND=5]="INVALID_GROUP_TYPE_FOUND",r[r.PUSH_MODE_DOES_NOT_EXIST=6]="PUSH_MODE_DOES_NOT_EXIST",r[r.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE=7]="MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE",r[r.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY=8]="MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY",r[r.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST=9]="MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST",r[r.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED=10]="LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED",r[r.SOI_ANCHOR_FOUND=11]="SOI_ANCHOR_FOUND",r[r.EMPTY_MATCH_PATTERN=12]="EMPTY_MATCH_PATTERN",r[r.NO_LINE_BREAKS_FLAGS=13]="NO_LINE_BREAKS_FLAGS",r[r.UNREACHABLE_PATTERN=14]="UNREACHABLE_PATTERN",r[r.IDENTIFY_TERMINATOR=15]="IDENTIFY_TERMINATOR",r[r.CUSTOM_LINE_BREAK=16]="CUSTOM_LINE_BREAK"})(VEe=Cc.LexerDefinitionErrorType||(Cc.LexerDefinitionErrorType={}));var bd={deferDefinitionErrorsHandling:!1,positionTracking:"full",lineTerminatorsPattern:/\n|\r\n?/g,lineTerminatorCharacters:[` +`,"\r"],ensureOptimizations:!1,safeMode:!1,errorMessageProvider:WEe.defaultLexerErrorProvider,traceInitPerf:!1,skipValidations:!1};Object.freeze(bd);var XEe=function(){function r(e,t){var i=this;if(t===void 0&&(t=bd),this.lexerDefinition=e,this.lexerDefinitionErrors=[],this.lexerDefinitionWarning=[],this.patternIdxToConfig={},this.charCodeToPatternIdxToConfig={},this.modes=[],this.emptyGroups={},this.config=void 0,this.trackStartLines=!0,this.trackEndLines=!0,this.hasCustom=!1,this.canModeBeOptimized={},typeof t=="boolean")throw Error(`The second argument to the Lexer constructor is now an ILexerConfig Object. +a boolean 2nd argument is no longer supported`);this.config=(0,nr.merge)(bd,t);var n=this.config.traceInitPerf;n===!0?(this.traceInitMaxIdent=1/0,this.traceInitPerf=!0):typeof n=="number"&&(this.traceInitMaxIdent=n,this.traceInitPerf=!0),this.traceInitIndent=-1,this.TRACE_INIT("Lexer Constructor",function(){var s,o=!0;i.TRACE_INIT("Lexer Config handling",function(){if(i.config.lineTerminatorsPattern===bd.lineTerminatorsPattern)i.config.lineTerminatorsPattern=_s.LineTerminatorOptimizedTester;else if(i.config.lineTerminatorCharacters===bd.lineTerminatorCharacters)throw Error(`Error: Missing property on the Lexer config. + For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#MISSING_LINE_TERM_CHARS`);if(t.safeMode&&t.ensureOptimizations)throw Error('"safeMode" and "ensureOptimizations" flags are mutually exclusive.');i.trackStartLines=/full|onlyStart/i.test(i.config.positionTracking),i.trackEndLines=/full/i.test(i.config.positionTracking),(0,nr.isArray)(e)?(s={modes:{}},s.modes[_s.DEFAULT_MODE]=(0,nr.cloneArr)(e),s[_s.DEFAULT_MODE]=_s.DEFAULT_MODE):(o=!1,s=(0,nr.cloneObj)(e))}),i.config.skipValidations===!1&&(i.TRACE_INIT("performRuntimeChecks",function(){i.lexerDefinitionErrors=i.lexerDefinitionErrors.concat((0,_s.performRuntimeChecks)(s,i.trackStartLines,i.config.lineTerminatorCharacters))}),i.TRACE_INIT("performWarningRuntimeChecks",function(){i.lexerDefinitionWarning=i.lexerDefinitionWarning.concat((0,_s.performWarningRuntimeChecks)(s,i.trackStartLines,i.config.lineTerminatorCharacters))})),s.modes=s.modes?s.modes:{},(0,nr.forEach)(s.modes,function(u,g){s.modes[g]=(0,nr.reject)(u,function(f){return(0,nr.isUndefined)(f)})});var a=(0,nr.keys)(s.modes);if((0,nr.forEach)(s.modes,function(u,g){i.TRACE_INIT("Mode: <"+g+"> processing",function(){if(i.modes.push(g),i.config.skipValidations===!1&&i.TRACE_INIT("validatePatterns",function(){i.lexerDefinitionErrors=i.lexerDefinitionErrors.concat((0,_s.validatePatterns)(u,a))}),(0,nr.isEmpty)(i.lexerDefinitionErrors)){(0,JEe.augmentTokenTypes)(u);var f;i.TRACE_INIT("analyzeTokenTypes",function(){f=(0,_s.analyzeTokenTypes)(u,{lineTerminatorCharacters:i.config.lineTerminatorCharacters,positionTracking:t.positionTracking,ensureOptimizations:t.ensureOptimizations,safeMode:t.safeMode,tracer:i.TRACE_INIT.bind(i)})}),i.patternIdxToConfig[g]=f.patternIdxToConfig,i.charCodeToPatternIdxToConfig[g]=f.charCodeToPatternIdxToConfig,i.emptyGroups=(0,nr.merge)(i.emptyGroups,f.emptyGroups),i.hasCustom=f.hasCustom||i.hasCustom,i.canModeBeOptimized[g]=f.canBeOptimized}})}),i.defaultMode=s.defaultMode,!(0,nr.isEmpty)(i.lexerDefinitionErrors)&&!i.config.deferDefinitionErrorsHandling){var l=(0,nr.map)(i.lexerDefinitionErrors,function(u){return u.message}),c=l.join(`----------------------- +`);throw new Error(`Errors detected in definition of Lexer: +`+c)}(0,nr.forEach)(i.lexerDefinitionWarning,function(u){(0,nr.PRINT_WARNING)(u.message)}),i.TRACE_INIT("Choosing sub-methods implementations",function(){if(_s.SUPPORT_STICKY?(i.chopInput=nr.IDENTITY,i.match=i.matchWithTest):(i.updateLastIndex=nr.NOOP,i.match=i.matchWithExec),o&&(i.handleModes=nr.NOOP),i.trackStartLines===!1&&(i.computeNewColumn=nr.IDENTITY),i.trackEndLines===!1&&(i.updateTokenEndLineColumnLocation=nr.NOOP),/full/i.test(i.config.positionTracking))i.createTokenInstance=i.createFullToken;else if(/onlyStart/i.test(i.config.positionTracking))i.createTokenInstance=i.createStartOnlyToken;else if(/onlyOffset/i.test(i.config.positionTracking))i.createTokenInstance=i.createOffsetOnlyToken;else throw Error('Invalid config option: "'+i.config.positionTracking+'"');i.hasCustom?(i.addToken=i.addTokenUsingPush,i.handlePayload=i.handlePayloadWithCustom):(i.addToken=i.addTokenUsingMemberAccess,i.handlePayload=i.handlePayloadNoCustom)}),i.TRACE_INIT("Failed Optimization Warnings",function(){var u=(0,nr.reduce)(i.canModeBeOptimized,function(g,f,h){return f===!1&&g.push(h),g},[]);if(t.ensureOptimizations&&!(0,nr.isEmpty)(u))throw Error("Lexer Modes: < "+u.join(", ")+` > cannot be optimized. + Disable the "ensureOptimizations" lexer config flag to silently ignore this and run the lexer in an un-optimized mode. + Or inspect the console log for details on how to resolve these issues.`)}),i.TRACE_INIT("clearRegExpParserCache",function(){(0,zEe.clearRegExpParserCache)()}),i.TRACE_INIT("toFastProperties",function(){(0,nr.toFastProperties)(i)})})}return r.prototype.tokenize=function(e,t){if(t===void 0&&(t=this.defaultMode),!(0,nr.isEmpty)(this.lexerDefinitionErrors)){var i=(0,nr.map)(this.lexerDefinitionErrors,function(o){return o.message}),n=i.join(`----------------------- +`);throw new Error(`Unable to Tokenize because Errors detected in definition of Lexer: +`+n)}var s=this.tokenizeInternal(e,t);return s},r.prototype.tokenizeInternal=function(e,t){var i=this,n,s,o,a,l,c,u,g,f,h,p,C,y,B,v,D,T=e,H=T.length,j=0,$=0,V=this.hasCustom?0:Math.floor(e.length/10),W=new Array(V),_=[],A=this.trackStartLines?1:void 0,Ae=this.trackStartLines?1:void 0,ge=(0,_s.cloneEmptyGroups)(this.emptyGroups),re=this.trackStartLines,M=this.config.lineTerminatorsPattern,F=0,ue=[],pe=[],ke=[],Fe=[];Object.freeze(Fe);var Ne=void 0;function oe(){return ue}function le(pr){var Ii=(0,_s.charCodeToOptimizedIndex)(pr),rs=pe[Ii];return rs===void 0?Fe:rs}var Be=function(pr){if(ke.length===1&&pr.tokenType.PUSH_MODE===void 0){var Ii=i.config.errorMessageProvider.buildUnableToPopLexerModeMessage(pr);_.push({offset:pr.startOffset,line:pr.startLine!==void 0?pr.startLine:void 0,column:pr.startColumn!==void 0?pr.startColumn:void 0,length:pr.image.length,message:Ii})}else{ke.pop();var rs=(0,nr.last)(ke);ue=i.patternIdxToConfig[rs],pe=i.charCodeToPatternIdxToConfig[rs],F=ue.length;var fa=i.canModeBeOptimized[rs]&&i.config.safeMode===!1;pe&&fa?Ne=le:Ne=oe}};function fe(pr){ke.push(pr),pe=this.charCodeToPatternIdxToConfig[pr],ue=this.patternIdxToConfig[pr],F=ue.length,F=ue.length;var Ii=this.canModeBeOptimized[pr]&&this.config.safeMode===!1;pe&&Ii?Ne=le:Ne=oe}fe.call(this,t);for(var ae;jc.length){c=a,u=g,ae=_e;break}}}break}}if(c!==null){if(f=c.length,h=ae.group,h!==void 0&&(p=ae.tokenTypeIdx,C=this.createTokenInstance(c,j,p,ae.tokenType,A,Ae,f),this.handlePayload(C,u),h===!1?$=this.addToken(W,$,C):ge[h].push(C)),e=this.chopInput(e,f),j=j+f,Ae=this.computeNewColumn(Ae,f),re===!0&&ae.canLineTerminator===!0){var It=0,Mr=void 0,ii=void 0;M.lastIndex=0;do Mr=M.test(c),Mr===!0&&(ii=M.lastIndex-1,It++);while(Mr===!0);It!==0&&(A=A+It,Ae=f-ii,this.updateTokenEndLineColumnLocation(C,h,ii,It,A,Ae,f))}this.handleModes(ae,Be,fe,C)}else{for(var gi=j,hr=A,fi=Ae,ni=!1;!ni&&j <"+e+">");var n=(0,nr.timer)(t),s=n.time,o=n.value,a=s>10?console.warn:console.log;return this.traceInitIndent time: "+s+"ms"),this.traceInitIndent--,o}else return t()},r.SKIPPED="This marks a skipped Token pattern, this means each token identified by it willbe consumed and then thrown into oblivion, this can be used to for example to completely ignore whitespace.",r.NA=/NOT_APPLICABLE/,r}();Cc.Lexer=XEe});var TA=w(Qi=>{"use strict";Object.defineProperty(Qi,"__esModule",{value:!0});Qi.tokenMatcher=Qi.createTokenInstance=Qi.EOF=Qi.createToken=Qi.hasTokenLabel=Qi.tokenName=Qi.tokenLabel=void 0;var $s=Gt(),ZEe=Bd(),Hv=_g();function _Ee(r){return bj(r)?r.LABEL:r.name}Qi.tokenLabel=_Ee;function $Ee(r){return r.name}Qi.tokenName=$Ee;function bj(r){return(0,$s.isString)(r.LABEL)&&r.LABEL!==""}Qi.hasTokenLabel=bj;var eIe="parent",dj="categories",Cj="label",mj="group",Ej="push_mode",Ij="pop_mode",yj="longer_alt",wj="line_breaks",Bj="start_chars_hint";function Qj(r){return tIe(r)}Qi.createToken=Qj;function tIe(r){var e=r.pattern,t={};if(t.name=r.name,(0,$s.isUndefined)(e)||(t.PATTERN=e),(0,$s.has)(r,eIe))throw`The parent property is no longer supported. +See: https://github.com/chevrotain/chevrotain/issues/564#issuecomment-349062346 for details.`;return(0,$s.has)(r,dj)&&(t.CATEGORIES=r[dj]),(0,Hv.augmentTokenTypes)([t]),(0,$s.has)(r,Cj)&&(t.LABEL=r[Cj]),(0,$s.has)(r,mj)&&(t.GROUP=r[mj]),(0,$s.has)(r,Ij)&&(t.POP_MODE=r[Ij]),(0,$s.has)(r,Ej)&&(t.PUSH_MODE=r[Ej]),(0,$s.has)(r,yj)&&(t.LONGER_ALT=r[yj]),(0,$s.has)(r,wj)&&(t.LINE_BREAKS=r[wj]),(0,$s.has)(r,Bj)&&(t.START_CHARS_HINT=r[Bj]),t}Qi.EOF=Qj({name:"EOF",pattern:ZEe.Lexer.NA});(0,Hv.augmentTokenTypes)([Qi.EOF]);function rIe(r,e,t,i,n,s,o,a){return{image:e,startOffset:t,endOffset:i,startLine:n,endLine:s,startColumn:o,endColumn:a,tokenTypeIdx:r.tokenTypeIdx,tokenType:r}}Qi.createTokenInstance=rIe;function iIe(r,e){return(0,Hv.tokenStructuredMatcher)(r,e)}Qi.tokenMatcher=iIe});var mn=w(zt=>{"use strict";var Pa=zt&&zt.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(zt,"__esModule",{value:!0});zt.serializeProduction=zt.serializeGrammar=zt.Terminal=zt.Alternation=zt.RepetitionWithSeparator=zt.Repetition=zt.RepetitionMandatoryWithSeparator=zt.RepetitionMandatory=zt.Option=zt.Alternative=zt.Rule=zt.NonTerminal=zt.AbstractProduction=void 0;var Ar=Gt(),nIe=TA(),Ro=function(){function r(e){this._definition=e}return Object.defineProperty(r.prototype,"definition",{get:function(){return this._definition},set:function(e){this._definition=e},enumerable:!1,configurable:!0}),r.prototype.accept=function(e){e.visit(this),(0,Ar.forEach)(this.definition,function(t){t.accept(e)})},r}();zt.AbstractProduction=Ro;var Sj=function(r){Pa(e,r);function e(t){var i=r.call(this,[])||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return Object.defineProperty(e.prototype,"definition",{get:function(){return this.referencedRule!==void 0?this.referencedRule.definition:[]},set:function(t){},enumerable:!1,configurable:!0}),e.prototype.accept=function(t){t.visit(this)},e}(Ro);zt.NonTerminal=Sj;var vj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.orgText="",(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.Rule=vj;var xj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.ignoreAmbiguities=!1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.Alternative=xj;var Pj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.Option=Pj;var Dj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.RepetitionMandatory=Dj;var kj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.RepetitionMandatoryWithSeparator=kj;var Rj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.Repetition=Rj;var Fj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return e}(Ro);zt.RepetitionWithSeparator=Fj;var Nj=function(r){Pa(e,r);function e(t){var i=r.call(this,t.definition)||this;return i.idx=1,i.ignoreAmbiguities=!1,i.hasPredicates=!1,(0,Ar.assign)(i,(0,Ar.pick)(t,function(n){return n!==void 0})),i}return Object.defineProperty(e.prototype,"definition",{get:function(){return this._definition},set:function(t){this._definition=t},enumerable:!1,configurable:!0}),e}(Ro);zt.Alternation=Nj;var oy=function(){function r(e){this.idx=1,(0,Ar.assign)(this,(0,Ar.pick)(e,function(t){return t!==void 0}))}return r.prototype.accept=function(e){e.visit(this)},r}();zt.Terminal=oy;function sIe(r){return(0,Ar.map)(r,Qd)}zt.serializeGrammar=sIe;function Qd(r){function e(s){return(0,Ar.map)(s,Qd)}if(r instanceof Sj){var t={type:"NonTerminal",name:r.nonTerminalName,idx:r.idx};return(0,Ar.isString)(r.label)&&(t.label=r.label),t}else{if(r instanceof xj)return{type:"Alternative",definition:e(r.definition)};if(r instanceof Pj)return{type:"Option",idx:r.idx,definition:e(r.definition)};if(r instanceof Dj)return{type:"RepetitionMandatory",idx:r.idx,definition:e(r.definition)};if(r instanceof kj)return{type:"RepetitionMandatoryWithSeparator",idx:r.idx,separator:Qd(new oy({terminalType:r.separator})),definition:e(r.definition)};if(r instanceof Fj)return{type:"RepetitionWithSeparator",idx:r.idx,separator:Qd(new oy({terminalType:r.separator})),definition:e(r.definition)};if(r instanceof Rj)return{type:"Repetition",idx:r.idx,definition:e(r.definition)};if(r instanceof Nj)return{type:"Alternation",idx:r.idx,definition:e(r.definition)};if(r instanceof oy){var i={type:"Terminal",name:r.terminalType.name,label:(0,nIe.tokenLabel)(r.terminalType),idx:r.idx};(0,Ar.isString)(r.label)&&(i.terminalLabel=r.label);var n=r.terminalType.PATTERN;return r.terminalType.PATTERN&&(i.pattern=(0,Ar.isRegExp)(n)?n.source:n),i}else{if(r instanceof vj)return{type:"Rule",name:r.name,orgText:r.orgText,definition:e(r.definition)};throw Error("non exhaustive match")}}}zt.serializeProduction=Qd});var Ay=w(ay=>{"use strict";Object.defineProperty(ay,"__esModule",{value:!0});ay.RestWalker=void 0;var Gv=Gt(),En=mn(),oIe=function(){function r(){}return r.prototype.walk=function(e,t){var i=this;t===void 0&&(t=[]),(0,Gv.forEach)(e.definition,function(n,s){var o=(0,Gv.drop)(e.definition,s+1);if(n instanceof En.NonTerminal)i.walkProdRef(n,o,t);else if(n instanceof En.Terminal)i.walkTerminal(n,o,t);else if(n instanceof En.Alternative)i.walkFlat(n,o,t);else if(n instanceof En.Option)i.walkOption(n,o,t);else if(n instanceof En.RepetitionMandatory)i.walkAtLeastOne(n,o,t);else if(n instanceof En.RepetitionMandatoryWithSeparator)i.walkAtLeastOneSep(n,o,t);else if(n instanceof En.RepetitionWithSeparator)i.walkManySep(n,o,t);else if(n instanceof En.Repetition)i.walkMany(n,o,t);else if(n instanceof En.Alternation)i.walkOr(n,o,t);else throw Error("non exhaustive match")})},r.prototype.walkTerminal=function(e,t,i){},r.prototype.walkProdRef=function(e,t,i){},r.prototype.walkFlat=function(e,t,i){var n=t.concat(i);this.walk(e,n)},r.prototype.walkOption=function(e,t,i){var n=t.concat(i);this.walk(e,n)},r.prototype.walkAtLeastOne=function(e,t,i){var n=[new En.Option({definition:e.definition})].concat(t,i);this.walk(e,n)},r.prototype.walkAtLeastOneSep=function(e,t,i){var n=Tj(e,t,i);this.walk(e,n)},r.prototype.walkMany=function(e,t,i){var n=[new En.Option({definition:e.definition})].concat(t,i);this.walk(e,n)},r.prototype.walkManySep=function(e,t,i){var n=Tj(e,t,i);this.walk(e,n)},r.prototype.walkOr=function(e,t,i){var n=this,s=t.concat(i);(0,Gv.forEach)(e.definition,function(o){var a=new En.Alternative({definition:[o]});n.walk(a,s)})},r}();ay.RestWalker=oIe;function Tj(r,e,t){var i=[new En.Option({definition:[new En.Terminal({terminalType:r.separator})].concat(r.definition)})],n=i.concat(e,t);return n}});var $g=w(ly=>{"use strict";Object.defineProperty(ly,"__esModule",{value:!0});ly.GAstVisitor=void 0;var Fo=mn(),aIe=function(){function r(){}return r.prototype.visit=function(e){var t=e;switch(t.constructor){case Fo.NonTerminal:return this.visitNonTerminal(t);case Fo.Alternative:return this.visitAlternative(t);case Fo.Option:return this.visitOption(t);case Fo.RepetitionMandatory:return this.visitRepetitionMandatory(t);case Fo.RepetitionMandatoryWithSeparator:return this.visitRepetitionMandatoryWithSeparator(t);case Fo.RepetitionWithSeparator:return this.visitRepetitionWithSeparator(t);case Fo.Repetition:return this.visitRepetition(t);case Fo.Alternation:return this.visitAlternation(t);case Fo.Terminal:return this.visitTerminal(t);case Fo.Rule:return this.visitRule(t);default:throw Error("non exhaustive match")}},r.prototype.visitNonTerminal=function(e){},r.prototype.visitAlternative=function(e){},r.prototype.visitOption=function(e){},r.prototype.visitRepetition=function(e){},r.prototype.visitRepetitionMandatory=function(e){},r.prototype.visitRepetitionMandatoryWithSeparator=function(e){},r.prototype.visitRepetitionWithSeparator=function(e){},r.prototype.visitAlternation=function(e){},r.prototype.visitTerminal=function(e){},r.prototype.visitRule=function(e){},r}();ly.GAstVisitor=aIe});var vd=w(Oi=>{"use strict";var AIe=Oi&&Oi.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Oi,"__esModule",{value:!0});Oi.collectMethods=Oi.DslMethodsCollectorVisitor=Oi.getProductionDslName=Oi.isBranchingProd=Oi.isOptionalProd=Oi.isSequenceProd=void 0;var Sd=Gt(),br=mn(),lIe=$g();function cIe(r){return r instanceof br.Alternative||r instanceof br.Option||r instanceof br.Repetition||r instanceof br.RepetitionMandatory||r instanceof br.RepetitionMandatoryWithSeparator||r instanceof br.RepetitionWithSeparator||r instanceof br.Terminal||r instanceof br.Rule}Oi.isSequenceProd=cIe;function Yv(r,e){e===void 0&&(e=[]);var t=r instanceof br.Option||r instanceof br.Repetition||r instanceof br.RepetitionWithSeparator;return t?!0:r instanceof br.Alternation?(0,Sd.some)(r.definition,function(i){return Yv(i,e)}):r instanceof br.NonTerminal&&(0,Sd.contains)(e,r)?!1:r instanceof br.AbstractProduction?(r instanceof br.NonTerminal&&e.push(r),(0,Sd.every)(r.definition,function(i){return Yv(i,e)})):!1}Oi.isOptionalProd=Yv;function uIe(r){return r instanceof br.Alternation}Oi.isBranchingProd=uIe;function gIe(r){if(r instanceof br.NonTerminal)return"SUBRULE";if(r instanceof br.Option)return"OPTION";if(r instanceof br.Alternation)return"OR";if(r instanceof br.RepetitionMandatory)return"AT_LEAST_ONE";if(r instanceof br.RepetitionMandatoryWithSeparator)return"AT_LEAST_ONE_SEP";if(r instanceof br.RepetitionWithSeparator)return"MANY_SEP";if(r instanceof br.Repetition)return"MANY";if(r instanceof br.Terminal)return"CONSUME";throw Error("non exhaustive match")}Oi.getProductionDslName=gIe;var Lj=function(r){AIe(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.separator="-",t.dslMethods={option:[],alternation:[],repetition:[],repetitionWithSeparator:[],repetitionMandatory:[],repetitionMandatoryWithSeparator:[]},t}return e.prototype.reset=function(){this.dslMethods={option:[],alternation:[],repetition:[],repetitionWithSeparator:[],repetitionMandatory:[],repetitionMandatoryWithSeparator:[]}},e.prototype.visitTerminal=function(t){var i=t.terminalType.name+this.separator+"Terminal";(0,Sd.has)(this.dslMethods,i)||(this.dslMethods[i]=[]),this.dslMethods[i].push(t)},e.prototype.visitNonTerminal=function(t){var i=t.nonTerminalName+this.separator+"Terminal";(0,Sd.has)(this.dslMethods,i)||(this.dslMethods[i]=[]),this.dslMethods[i].push(t)},e.prototype.visitOption=function(t){this.dslMethods.option.push(t)},e.prototype.visitRepetitionWithSeparator=function(t){this.dslMethods.repetitionWithSeparator.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.dslMethods.repetitionMandatory.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.dslMethods.repetitionMandatoryWithSeparator.push(t)},e.prototype.visitRepetition=function(t){this.dslMethods.repetition.push(t)},e.prototype.visitAlternation=function(t){this.dslMethods.alternation.push(t)},e}(lIe.GAstVisitor);Oi.DslMethodsCollectorVisitor=Lj;var cy=new Lj;function fIe(r){cy.reset(),r.accept(cy);var e=cy.dslMethods;return cy.reset(),e}Oi.collectMethods=fIe});var qv=w(No=>{"use strict";Object.defineProperty(No,"__esModule",{value:!0});No.firstForTerminal=No.firstForBranching=No.firstForSequence=No.first=void 0;var uy=Gt(),Mj=mn(),jv=vd();function gy(r){if(r instanceof Mj.NonTerminal)return gy(r.referencedRule);if(r instanceof Mj.Terminal)return Uj(r);if((0,jv.isSequenceProd)(r))return Oj(r);if((0,jv.isBranchingProd)(r))return Kj(r);throw Error("non exhaustive match")}No.first=gy;function Oj(r){for(var e=[],t=r.definition,i=0,n=t.length>i,s,o=!0;n&&o;)s=t[i],o=(0,jv.isOptionalProd)(s),e=e.concat(gy(s)),i=i+1,n=t.length>i;return(0,uy.uniq)(e)}No.firstForSequence=Oj;function Kj(r){var e=(0,uy.map)(r.definition,function(t){return gy(t)});return(0,uy.uniq)((0,uy.flatten)(e))}No.firstForBranching=Kj;function Uj(r){return[r.terminalType]}No.firstForTerminal=Uj});var Jv=w(fy=>{"use strict";Object.defineProperty(fy,"__esModule",{value:!0});fy.IN=void 0;fy.IN="_~IN~_"});var qj=w(fs=>{"use strict";var hIe=fs&&fs.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(fs,"__esModule",{value:!0});fs.buildInProdFollowPrefix=fs.buildBetweenProdsFollowPrefix=fs.computeAllProdsFollows=fs.ResyncFollowsWalker=void 0;var pIe=Ay(),dIe=qv(),Hj=Gt(),Gj=Jv(),CIe=mn(),Yj=function(r){hIe(e,r);function e(t){var i=r.call(this)||this;return i.topProd=t,i.follows={},i}return e.prototype.startWalking=function(){return this.walk(this.topProd),this.follows},e.prototype.walkTerminal=function(t,i,n){},e.prototype.walkProdRef=function(t,i,n){var s=jj(t.referencedRule,t.idx)+this.topProd.name,o=i.concat(n),a=new CIe.Alternative({definition:o}),l=(0,dIe.first)(a);this.follows[s]=l},e}(pIe.RestWalker);fs.ResyncFollowsWalker=Yj;function mIe(r){var e={};return(0,Hj.forEach)(r,function(t){var i=new Yj(t).startWalking();(0,Hj.assign)(e,i)}),e}fs.computeAllProdsFollows=mIe;function jj(r,e){return r.name+e+Gj.IN}fs.buildBetweenProdsFollowPrefix=jj;function EIe(r){var e=r.terminalType.name;return e+r.idx+Gj.IN}fs.buildInProdFollowPrefix=EIe});var xd=w(Da=>{"use strict";Object.defineProperty(Da,"__esModule",{value:!0});Da.defaultGrammarValidatorErrorProvider=Da.defaultGrammarResolverErrorProvider=Da.defaultParserErrorProvider=void 0;var ef=TA(),IIe=Gt(),eo=Gt(),Wv=mn(),Jj=vd();Da.defaultParserErrorProvider={buildMismatchTokenMessage:function(r){var e=r.expected,t=r.actual,i=r.previous,n=r.ruleName,s=(0,ef.hasTokenLabel)(e),o=s?"--> "+(0,ef.tokenLabel)(e)+" <--":"token of type --> "+e.name+" <--",a="Expecting "+o+" but found --> '"+t.image+"' <--";return a},buildNotAllInputParsedMessage:function(r){var e=r.firstRedundant,t=r.ruleName;return"Redundant input, expecting EOF but found: "+e.image},buildNoViableAltMessage:function(r){var e=r.expectedPathsPerAlt,t=r.actual,i=r.previous,n=r.customUserDescription,s=r.ruleName,o="Expecting: ",a=(0,eo.first)(t).image,l=` +but found: '`+a+"'";if(n)return o+n+l;var c=(0,eo.reduce)(e,function(h,p){return h.concat(p)},[]),u=(0,eo.map)(c,function(h){return"["+(0,eo.map)(h,function(p){return(0,ef.tokenLabel)(p)}).join(", ")+"]"}),g=(0,eo.map)(u,function(h,p){return" "+(p+1)+". "+h}),f=`one of these possible Token sequences: +`+g.join(` +`);return o+f+l},buildEarlyExitMessage:function(r){var e=r.expectedIterationPaths,t=r.actual,i=r.customUserDescription,n=r.ruleName,s="Expecting: ",o=(0,eo.first)(t).image,a=` +but found: '`+o+"'";if(i)return s+i+a;var l=(0,eo.map)(e,function(u){return"["+(0,eo.map)(u,function(g){return(0,ef.tokenLabel)(g)}).join(",")+"]"}),c=`expecting at least one iteration which starts with one of these possible Token sequences:: + `+("<"+l.join(" ,")+">");return s+c+a}};Object.freeze(Da.defaultParserErrorProvider);Da.defaultGrammarResolverErrorProvider={buildRuleNotFoundError:function(r,e){var t="Invalid grammar, reference to a rule which is not defined: ->"+e.nonTerminalName+`<- +inside top level rule: ->`+r.name+"<-";return t}};Da.defaultGrammarValidatorErrorProvider={buildDuplicateFoundError:function(r,e){function t(u){return u instanceof Wv.Terminal?u.terminalType.name:u instanceof Wv.NonTerminal?u.nonTerminalName:""}var i=r.name,n=(0,eo.first)(e),s=n.idx,o=(0,Jj.getProductionDslName)(n),a=t(n),l=s>0,c="->"+o+(l?s:"")+"<- "+(a?"with argument: ->"+a+"<-":"")+` + appears more than once (`+e.length+" times) in the top level rule: ->"+i+`<-. + For further details see: https://chevrotain.io/docs/FAQ.html#NUMERICAL_SUFFIXES + `;return c=c.replace(/[ \t]+/g," "),c=c.replace(/\s\s+/g,` +`),c},buildNamespaceConflictError:function(r){var e=`Namespace conflict found in grammar. +`+("The grammar has both a Terminal(Token) and a Non-Terminal(Rule) named: <"+r.name+`>. +`)+`To resolve this make sure each Terminal and Non-Terminal names are unique +This is easy to accomplish by using the convention that Terminal names start with an uppercase letter +and Non-Terminal names start with a lower case letter.`;return e},buildAlternationPrefixAmbiguityError:function(r){var e=(0,eo.map)(r.prefixPath,function(n){return(0,ef.tokenLabel)(n)}).join(", "),t=r.alternation.idx===0?"":r.alternation.idx,i="Ambiguous alternatives: <"+r.ambiguityIndices.join(" ,")+`> due to common lookahead prefix +`+("in inside <"+r.topLevelRule.name+`> Rule, +`)+("<"+e+`> may appears as a prefix path in all these alternatives. +`)+`See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#COMMON_PREFIX +For Further details.`;return i},buildAlternationAmbiguityError:function(r){var e=(0,eo.map)(r.prefixPath,function(n){return(0,ef.tokenLabel)(n)}).join(", "),t=r.alternation.idx===0?"":r.alternation.idx,i="Ambiguous Alternatives Detected: <"+r.ambiguityIndices.join(" ,")+"> in "+(" inside <"+r.topLevelRule.name+`> Rule, +`)+("<"+e+`> may appears as a prefix path in all these alternatives. +`);return i=i+`See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#AMBIGUOUS_ALTERNATIVES +For Further details.`,i},buildEmptyRepetitionError:function(r){var e=(0,Jj.getProductionDslName)(r.repetition);r.repetition.idx!==0&&(e+=r.repetition.idx);var t="The repetition <"+e+"> within Rule <"+r.topLevelRule.name+`> can never consume any tokens. +This could lead to an infinite loop.`;return t},buildTokenNameError:function(r){return"deprecated"},buildEmptyAlternationError:function(r){var e="Ambiguous empty alternative: <"+(r.emptyChoiceIdx+1)+">"+(" in inside <"+r.topLevelRule.name+`> Rule. +`)+"Only the last alternative may be an empty alternative.";return e},buildTooManyAlternativesError:function(r){var e=`An Alternation cannot have more than 256 alternatives: +`+(" inside <"+r.topLevelRule.name+`> Rule. + has `+(r.alternation.definition.length+1)+" alternatives.");return e},buildLeftRecursionError:function(r){var e=r.topLevelRule.name,t=IIe.map(r.leftRecursionPath,function(s){return s.name}),i=e+" --> "+t.concat([e]).join(" --> "),n=`Left Recursion found in grammar. +`+("rule: <"+e+`> can be invoked from itself (directly or indirectly) +`)+(`without consuming any Tokens. The grammar path that causes this is: + `+i+` +`)+` To fix this refactor your grammar to remove the left recursion. +see: https://en.wikipedia.org/wiki/LL_parser#Left_Factoring.`;return n},buildInvalidRuleNameError:function(r){return"deprecated"},buildDuplicateRuleNameError:function(r){var e;r.topLevelRule instanceof Wv.Rule?e=r.topLevelRule.name:e=r.topLevelRule;var t="Duplicate definition, rule: ->"+e+"<- is already defined in the grammar: ->"+r.grammarName+"<-";return t}}});var Vj=w(LA=>{"use strict";var yIe=LA&&LA.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(LA,"__esModule",{value:!0});LA.GastRefResolverVisitor=LA.resolveGrammar=void 0;var wIe=jn(),Wj=Gt(),BIe=$g();function bIe(r,e){var t=new zj(r,e);return t.resolveRefs(),t.errors}LA.resolveGrammar=bIe;var zj=function(r){yIe(e,r);function e(t,i){var n=r.call(this)||this;return n.nameToTopRule=t,n.errMsgProvider=i,n.errors=[],n}return e.prototype.resolveRefs=function(){var t=this;(0,Wj.forEach)((0,Wj.values)(this.nameToTopRule),function(i){t.currTopLevel=i,i.accept(t)})},e.prototype.visitNonTerminal=function(t){var i=this.nameToTopRule[t.nonTerminalName];if(i)t.referencedRule=i;else{var n=this.errMsgProvider.buildRuleNotFoundError(this.currTopLevel,t);this.errors.push({message:n,type:wIe.ParserDefinitionErrorType.UNRESOLVED_SUBRULE_REF,ruleName:this.currTopLevel.name,unresolvedRefName:t.nonTerminalName})}},e}(BIe.GAstVisitor);LA.GastRefResolverVisitor=zj});var Dd=w(Nr=>{"use strict";var mc=Nr&&Nr.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Nr,"__esModule",{value:!0});Nr.nextPossibleTokensAfter=Nr.possiblePathsFrom=Nr.NextTerminalAfterAtLeastOneSepWalker=Nr.NextTerminalAfterAtLeastOneWalker=Nr.NextTerminalAfterManySepWalker=Nr.NextTerminalAfterManyWalker=Nr.AbstractNextTerminalAfterProductionWalker=Nr.NextAfterTokenWalker=Nr.AbstractNextPossibleTokensWalker=void 0;var Xj=Ay(),Kt=Gt(),QIe=qv(),kt=mn(),Zj=function(r){mc(e,r);function e(t,i){var n=r.call(this)||this;return n.topProd=t,n.path=i,n.possibleTokTypes=[],n.nextProductionName="",n.nextProductionOccurrence=0,n.found=!1,n.isAtEndOfPath=!1,n}return e.prototype.startWalking=function(){if(this.found=!1,this.path.ruleStack[0]!==this.topProd.name)throw Error("The path does not start with the walker's top Rule!");return this.ruleStack=(0,Kt.cloneArr)(this.path.ruleStack).reverse(),this.occurrenceStack=(0,Kt.cloneArr)(this.path.occurrenceStack).reverse(),this.ruleStack.pop(),this.occurrenceStack.pop(),this.updateExpectedNext(),this.walk(this.topProd),this.possibleTokTypes},e.prototype.walk=function(t,i){i===void 0&&(i=[]),this.found||r.prototype.walk.call(this,t,i)},e.prototype.walkProdRef=function(t,i,n){if(t.referencedRule.name===this.nextProductionName&&t.idx===this.nextProductionOccurrence){var s=i.concat(n);this.updateExpectedNext(),this.walk(t.referencedRule,s)}},e.prototype.updateExpectedNext=function(){(0,Kt.isEmpty)(this.ruleStack)?(this.nextProductionName="",this.nextProductionOccurrence=0,this.isAtEndOfPath=!0):(this.nextProductionName=this.ruleStack.pop(),this.nextProductionOccurrence=this.occurrenceStack.pop())},e}(Xj.RestWalker);Nr.AbstractNextPossibleTokensWalker=Zj;var SIe=function(r){mc(e,r);function e(t,i){var n=r.call(this,t,i)||this;return n.path=i,n.nextTerminalName="",n.nextTerminalOccurrence=0,n.nextTerminalName=n.path.lastTok.name,n.nextTerminalOccurrence=n.path.lastTokOccurrence,n}return e.prototype.walkTerminal=function(t,i,n){if(this.isAtEndOfPath&&t.terminalType.name===this.nextTerminalName&&t.idx===this.nextTerminalOccurrence&&!this.found){var s=i.concat(n),o=new kt.Alternative({definition:s});this.possibleTokTypes=(0,QIe.first)(o),this.found=!0}},e}(Zj);Nr.NextAfterTokenWalker=SIe;var Pd=function(r){mc(e,r);function e(t,i){var n=r.call(this)||this;return n.topRule=t,n.occurrence=i,n.result={token:void 0,occurrence:void 0,isEndOfRule:void 0},n}return e.prototype.startWalking=function(){return this.walk(this.topRule),this.result},e}(Xj.RestWalker);Nr.AbstractNextTerminalAfterProductionWalker=Pd;var vIe=function(r){mc(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkMany=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkMany.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterManyWalker=vIe;var xIe=function(r){mc(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkManySep=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkManySep.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterManySepWalker=xIe;var PIe=function(r){mc(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkAtLeastOne=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkAtLeastOne.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterAtLeastOneWalker=PIe;var DIe=function(r){mc(e,r);function e(){return r!==null&&r.apply(this,arguments)||this}return e.prototype.walkAtLeastOneSep=function(t,i,n){if(t.idx===this.occurrence){var s=(0,Kt.first)(i.concat(n));this.result.isEndOfRule=s===void 0,s instanceof kt.Terminal&&(this.result.token=s.terminalType,this.result.occurrence=s.idx)}else r.prototype.walkAtLeastOneSep.call(this,t,i,n)},e}(Pd);Nr.NextTerminalAfterAtLeastOneSepWalker=DIe;function _j(r,e,t){t===void 0&&(t=[]),t=(0,Kt.cloneArr)(t);var i=[],n=0;function s(c){return c.concat((0,Kt.drop)(r,n+1))}function o(c){var u=_j(s(c),e,t);return i.concat(u)}for(;t.length=0;ge--){var re=B.definition[ge],M={idx:p,def:re.definition.concat((0,Kt.drop)(h)),ruleStack:C,occurrenceStack:y};g.push(M),g.push(o)}else if(B instanceof kt.Alternative)g.push({idx:p,def:B.definition.concat((0,Kt.drop)(h)),ruleStack:C,occurrenceStack:y});else if(B instanceof kt.Rule)g.push(RIe(B,p,C,y));else throw Error("non exhaustive match")}}return u}Nr.nextPossibleTokensAfter=kIe;function RIe(r,e,t,i){var n=(0,Kt.cloneArr)(t);n.push(r.name);var s=(0,Kt.cloneArr)(i);return s.push(1),{idx:e,def:r.definition,ruleStack:n,occurrenceStack:s}}});var kd=w(Zt=>{"use strict";var tq=Zt&&Zt.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Zt,"__esModule",{value:!0});Zt.areTokenCategoriesNotUsed=Zt.isStrictPrefixOfPath=Zt.containsPath=Zt.getLookaheadPathsForOptionalProd=Zt.getLookaheadPathsForOr=Zt.lookAheadSequenceFromAlternatives=Zt.buildSingleAlternativeLookaheadFunction=Zt.buildAlternativesLookAheadFunc=Zt.buildLookaheadFuncForOptionalProd=Zt.buildLookaheadFuncForOr=Zt.getProdType=Zt.PROD_TYPE=void 0;var sr=Gt(),$j=Dd(),FIe=Ay(),hy=_g(),MA=mn(),NIe=$g(),oi;(function(r){r[r.OPTION=0]="OPTION",r[r.REPETITION=1]="REPETITION",r[r.REPETITION_MANDATORY=2]="REPETITION_MANDATORY",r[r.REPETITION_MANDATORY_WITH_SEPARATOR=3]="REPETITION_MANDATORY_WITH_SEPARATOR",r[r.REPETITION_WITH_SEPARATOR=4]="REPETITION_WITH_SEPARATOR",r[r.ALTERNATION=5]="ALTERNATION"})(oi=Zt.PROD_TYPE||(Zt.PROD_TYPE={}));function TIe(r){if(r instanceof MA.Option)return oi.OPTION;if(r instanceof MA.Repetition)return oi.REPETITION;if(r instanceof MA.RepetitionMandatory)return oi.REPETITION_MANDATORY;if(r instanceof MA.RepetitionMandatoryWithSeparator)return oi.REPETITION_MANDATORY_WITH_SEPARATOR;if(r instanceof MA.RepetitionWithSeparator)return oi.REPETITION_WITH_SEPARATOR;if(r instanceof MA.Alternation)return oi.ALTERNATION;throw Error("non exhaustive match")}Zt.getProdType=TIe;function LIe(r,e,t,i,n,s){var o=iq(r,e,t),a=Xv(o)?hy.tokenStructuredMatcherNoCategories:hy.tokenStructuredMatcher;return s(o,i,a,n)}Zt.buildLookaheadFuncForOr=LIe;function MIe(r,e,t,i,n,s){var o=nq(r,e,n,t),a=Xv(o)?hy.tokenStructuredMatcherNoCategories:hy.tokenStructuredMatcher;return s(o[0],a,i)}Zt.buildLookaheadFuncForOptionalProd=MIe;function OIe(r,e,t,i){var n=r.length,s=(0,sr.every)(r,function(l){return(0,sr.every)(l,function(c){return c.length===1})});if(e)return function(l){for(var c=(0,sr.map)(l,function(D){return D.GATE}),u=0;u{"use strict";var Zv=Vt&&Vt.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(Vt,"__esModule",{value:!0});Vt.checkPrefixAlternativesAmbiguities=Vt.validateSomeNonEmptyLookaheadPath=Vt.validateTooManyAlts=Vt.RepetionCollector=Vt.validateAmbiguousAlternationAlternatives=Vt.validateEmptyOrAlternative=Vt.getFirstNoneTerminal=Vt.validateNoLeftRecursion=Vt.validateRuleIsOverridden=Vt.validateRuleDoesNotAlreadyExist=Vt.OccurrenceValidationCollector=Vt.identifyProductionForDuplicates=Vt.validateGrammar=void 0;var er=Gt(),Qr=Gt(),To=jn(),_v=vd(),tf=kd(),YIe=Dd(),to=mn(),$v=$g();function jIe(r,e,t,i,n){var s=er.map(r,function(h){return qIe(h,i)}),o=er.map(r,function(h){return ex(h,h,i)}),a=[],l=[],c=[];(0,Qr.every)(o,Qr.isEmpty)&&(a=(0,Qr.map)(r,function(h){return cq(h,i)}),l=(0,Qr.map)(r,function(h){return uq(h,e,i)}),c=hq(r,e,i));var u=zIe(r,t,i),g=(0,Qr.map)(r,function(h){return fq(h,i)}),f=(0,Qr.map)(r,function(h){return lq(h,r,n,i)});return er.flatten(s.concat(c,o,a,l,u,g,f))}Vt.validateGrammar=jIe;function qIe(r,e){var t=new Aq;r.accept(t);var i=t.allProductions,n=er.groupBy(i,oq),s=er.pick(n,function(a){return a.length>1}),o=er.map(er.values(s),function(a){var l=er.first(a),c=e.buildDuplicateFoundError(r,a),u=(0,_v.getProductionDslName)(l),g={message:c,type:To.ParserDefinitionErrorType.DUPLICATE_PRODUCTIONS,ruleName:r.name,dslName:u,occurrence:l.idx},f=aq(l);return f&&(g.parameter=f),g});return o}function oq(r){return(0,_v.getProductionDslName)(r)+"_#_"+r.idx+"_#_"+aq(r)}Vt.identifyProductionForDuplicates=oq;function aq(r){return r instanceof to.Terminal?r.terminalType.name:r instanceof to.NonTerminal?r.nonTerminalName:""}var Aq=function(r){Zv(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.allProductions=[],t}return e.prototype.visitNonTerminal=function(t){this.allProductions.push(t)},e.prototype.visitOption=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetition=function(t){this.allProductions.push(t)},e.prototype.visitAlternation=function(t){this.allProductions.push(t)},e.prototype.visitTerminal=function(t){this.allProductions.push(t)},e}($v.GAstVisitor);Vt.OccurrenceValidationCollector=Aq;function lq(r,e,t,i){var n=[],s=(0,Qr.reduce)(e,function(a,l){return l.name===r.name?a+1:a},0);if(s>1){var o=i.buildDuplicateRuleNameError({topLevelRule:r,grammarName:t});n.push({message:o,type:To.ParserDefinitionErrorType.DUPLICATE_RULE_NAME,ruleName:r.name})}return n}Vt.validateRuleDoesNotAlreadyExist=lq;function JIe(r,e,t){var i=[],n;return er.contains(e,r)||(n="Invalid rule override, rule: ->"+r+"<- cannot be overridden in the grammar: ->"+t+"<-as it is not defined in any of the super grammars ",i.push({message:n,type:To.ParserDefinitionErrorType.INVALID_RULE_OVERRIDE,ruleName:r})),i}Vt.validateRuleIsOverridden=JIe;function ex(r,e,t,i){i===void 0&&(i=[]);var n=[],s=Rd(e.definition);if(er.isEmpty(s))return[];var o=r.name,a=er.contains(s,r);a&&n.push({message:t.buildLeftRecursionError({topLevelRule:r,leftRecursionPath:i}),type:To.ParserDefinitionErrorType.LEFT_RECURSION,ruleName:o});var l=er.difference(s,i.concat([r])),c=er.map(l,function(u){var g=er.cloneArr(i);return g.push(u),ex(r,u,t,g)});return n.concat(er.flatten(c))}Vt.validateNoLeftRecursion=ex;function Rd(r){var e=[];if(er.isEmpty(r))return e;var t=er.first(r);if(t instanceof to.NonTerminal)e.push(t.referencedRule);else if(t instanceof to.Alternative||t instanceof to.Option||t instanceof to.RepetitionMandatory||t instanceof to.RepetitionMandatoryWithSeparator||t instanceof to.RepetitionWithSeparator||t instanceof to.Repetition)e=e.concat(Rd(t.definition));else if(t instanceof to.Alternation)e=er.flatten(er.map(t.definition,function(o){return Rd(o.definition)}));else if(!(t instanceof to.Terminal))throw Error("non exhaustive match");var i=(0,_v.isOptionalProd)(t),n=r.length>1;if(i&&n){var s=er.drop(r);return e.concat(Rd(s))}else return e}Vt.getFirstNoneTerminal=Rd;var tx=function(r){Zv(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.alternations=[],t}return e.prototype.visitAlternation=function(t){this.alternations.push(t)},e}($v.GAstVisitor);function cq(r,e){var t=new tx;r.accept(t);var i=t.alternations,n=er.reduce(i,function(s,o){var a=er.dropRight(o.definition),l=er.map(a,function(c,u){var g=(0,YIe.nextPossibleTokensAfter)([c],[],null,1);return er.isEmpty(g)?{message:e.buildEmptyAlternationError({topLevelRule:r,alternation:o,emptyChoiceIdx:u}),type:To.ParserDefinitionErrorType.NONE_LAST_EMPTY_ALT,ruleName:r.name,occurrence:o.idx,alternative:u+1}:null});return s.concat(er.compact(l))},[]);return n}Vt.validateEmptyOrAlternative=cq;function uq(r,e,t){var i=new tx;r.accept(i);var n=i.alternations;n=(0,Qr.reject)(n,function(o){return o.ignoreAmbiguities===!0});var s=er.reduce(n,function(o,a){var l=a.idx,c=a.maxLookahead||e,u=(0,tf.getLookaheadPathsForOr)(l,r,c,a),g=WIe(u,a,r,t),f=pq(u,a,r,t);return o.concat(g,f)},[]);return s}Vt.validateAmbiguousAlternationAlternatives=uq;var gq=function(r){Zv(e,r);function e(){var t=r!==null&&r.apply(this,arguments)||this;return t.allProductions=[],t}return e.prototype.visitRepetitionWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatory=function(t){this.allProductions.push(t)},e.prototype.visitRepetitionMandatoryWithSeparator=function(t){this.allProductions.push(t)},e.prototype.visitRepetition=function(t){this.allProductions.push(t)},e}($v.GAstVisitor);Vt.RepetionCollector=gq;function fq(r,e){var t=new tx;r.accept(t);var i=t.alternations,n=er.reduce(i,function(s,o){return o.definition.length>255&&s.push({message:e.buildTooManyAlternativesError({topLevelRule:r,alternation:o}),type:To.ParserDefinitionErrorType.TOO_MANY_ALTS,ruleName:r.name,occurrence:o.idx}),s},[]);return n}Vt.validateTooManyAlts=fq;function hq(r,e,t){var i=[];return(0,Qr.forEach)(r,function(n){var s=new gq;n.accept(s);var o=s.allProductions;(0,Qr.forEach)(o,function(a){var l=(0,tf.getProdType)(a),c=a.maxLookahead||e,u=a.idx,g=(0,tf.getLookaheadPathsForOptionalProd)(u,n,l,c),f=g[0];if((0,Qr.isEmpty)((0,Qr.flatten)(f))){var h=t.buildEmptyRepetitionError({topLevelRule:n,repetition:a});i.push({message:h,type:To.ParserDefinitionErrorType.NO_NON_EMPTY_LOOKAHEAD,ruleName:n.name})}})}),i}Vt.validateSomeNonEmptyLookaheadPath=hq;function WIe(r,e,t,i){var n=[],s=(0,Qr.reduce)(r,function(a,l,c){return e.definition[c].ignoreAmbiguities===!0||(0,Qr.forEach)(l,function(u){var g=[c];(0,Qr.forEach)(r,function(f,h){c!==h&&(0,tf.containsPath)(f,u)&&e.definition[h].ignoreAmbiguities!==!0&&g.push(h)}),g.length>1&&!(0,tf.containsPath)(n,u)&&(n.push(u),a.push({alts:g,path:u}))}),a},[]),o=er.map(s,function(a){var l=(0,Qr.map)(a.alts,function(u){return u+1}),c=i.buildAlternationAmbiguityError({topLevelRule:t,alternation:e,ambiguityIndices:l,prefixPath:a.path});return{message:c,type:To.ParserDefinitionErrorType.AMBIGUOUS_ALTS,ruleName:t.name,occurrence:e.idx,alternatives:[a.alts]}});return o}function pq(r,e,t,i){var n=[],s=(0,Qr.reduce)(r,function(o,a,l){var c=(0,Qr.map)(a,function(u){return{idx:l,path:u}});return o.concat(c)},[]);return(0,Qr.forEach)(s,function(o){var a=e.definition[o.idx];if(a.ignoreAmbiguities!==!0){var l=o.idx,c=o.path,u=(0,Qr.findAll)(s,function(f){return e.definition[f.idx].ignoreAmbiguities!==!0&&f.idx{"use strict";Object.defineProperty(rf,"__esModule",{value:!0});rf.validateGrammar=rf.resolveGrammar=void 0;var ix=Gt(),VIe=Vj(),XIe=rx(),dq=xd();function ZIe(r){r=(0,ix.defaults)(r,{errMsgProvider:dq.defaultGrammarResolverErrorProvider});var e={};return(0,ix.forEach)(r.rules,function(t){e[t.name]=t}),(0,VIe.resolveGrammar)(e,r.errMsgProvider)}rf.resolveGrammar=ZIe;function _Ie(r){return r=(0,ix.defaults)(r,{errMsgProvider:dq.defaultGrammarValidatorErrorProvider}),(0,XIe.validateGrammar)(r.rules,r.maxLookahead,r.tokenTypes,r.errMsgProvider,r.grammarName)}rf.validateGrammar=_Ie});var nf=w(In=>{"use strict";var Fd=In&&In.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(In,"__esModule",{value:!0});In.EarlyExitException=In.NotAllInputParsedException=In.NoViableAltException=In.MismatchedTokenException=In.isRecognitionException=void 0;var $Ie=Gt(),mq="MismatchedTokenException",Eq="NoViableAltException",Iq="EarlyExitException",yq="NotAllInputParsedException",wq=[mq,Eq,Iq,yq];Object.freeze(wq);function eye(r){return(0,$Ie.contains)(wq,r.name)}In.isRecognitionException=eye;var py=function(r){Fd(e,r);function e(t,i){var n=this.constructor,s=r.call(this,t)||this;return s.token=i,s.resyncedTokens=[],Object.setPrototypeOf(s,n.prototype),Error.captureStackTrace&&Error.captureStackTrace(s,s.constructor),s}return e}(Error),tye=function(r){Fd(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=mq,s}return e}(py);In.MismatchedTokenException=tye;var rye=function(r){Fd(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=Eq,s}return e}(py);In.NoViableAltException=rye;var iye=function(r){Fd(e,r);function e(t,i){var n=r.call(this,t,i)||this;return n.name=yq,n}return e}(py);In.NotAllInputParsedException=iye;var nye=function(r){Fd(e,r);function e(t,i,n){var s=r.call(this,t,i)||this;return s.previousToken=n,s.name=Iq,s}return e}(py);In.EarlyExitException=nye});var sx=w(Ki=>{"use strict";Object.defineProperty(Ki,"__esModule",{value:!0});Ki.attemptInRepetitionRecovery=Ki.Recoverable=Ki.InRuleRecoveryException=Ki.IN_RULE_RECOVERY_EXCEPTION=Ki.EOF_FOLLOW_KEY=void 0;var dy=TA(),hs=Gt(),sye=nf(),oye=Jv(),aye=jn();Ki.EOF_FOLLOW_KEY={};Ki.IN_RULE_RECOVERY_EXCEPTION="InRuleRecoveryException";function nx(r){this.name=Ki.IN_RULE_RECOVERY_EXCEPTION,this.message=r}Ki.InRuleRecoveryException=nx;nx.prototype=Error.prototype;var Aye=function(){function r(){}return r.prototype.initRecoverable=function(e){this.firstAfterRepMap={},this.resyncFollows={},this.recoveryEnabled=(0,hs.has)(e,"recoveryEnabled")?e.recoveryEnabled:aye.DEFAULT_PARSER_CONFIG.recoveryEnabled,this.recoveryEnabled&&(this.attemptInRepetitionRecovery=Bq)},r.prototype.getTokenToInsert=function(e){var t=(0,dy.createTokenInstance)(e,"",NaN,NaN,NaN,NaN,NaN,NaN);return t.isInsertedInRecovery=!0,t},r.prototype.canTokenTypeBeInsertedInRecovery=function(e){return!0},r.prototype.tryInRepetitionRecovery=function(e,t,i,n){for(var s=this,o=this.findReSyncTokenType(),a=this.exportLexerState(),l=[],c=!1,u=this.LA(1),g=this.LA(1),f=function(){var h=s.LA(0),p=s.errorMessageProvider.buildMismatchTokenMessage({expected:n,actual:u,previous:h,ruleName:s.getCurrRuleFullName()}),C=new sye.MismatchedTokenException(p,u,s.LA(0));C.resyncedTokens=(0,hs.dropRight)(l),s.SAVE_ERROR(C)};!c;)if(this.tokenMatcher(g,n)){f();return}else if(i.call(this)){f(),e.apply(this,t);return}else this.tokenMatcher(g,o)?c=!0:(g=this.SKIP_TOKEN(),this.addToResyncTokens(g,l));this.importLexerState(a)},r.prototype.shouldInRepetitionRecoveryBeTried=function(e,t,i){return!(i===!1||e===void 0||t===void 0||this.tokenMatcher(this.LA(1),e)||this.isBackTracking()||this.canPerformInRuleRecovery(e,this.getFollowsForInRuleRecovery(e,t)))},r.prototype.getFollowsForInRuleRecovery=function(e,t){var i=this.getCurrentGrammarPath(e,t),n=this.getNextPossibleTokenTypes(i);return n},r.prototype.tryInRuleRecovery=function(e,t){if(this.canRecoverWithSingleTokenInsertion(e,t)){var i=this.getTokenToInsert(e);return i}if(this.canRecoverWithSingleTokenDeletion(e)){var n=this.SKIP_TOKEN();return this.consumeToken(),n}throw new nx("sad sad panda")},r.prototype.canPerformInRuleRecovery=function(e,t){return this.canRecoverWithSingleTokenInsertion(e,t)||this.canRecoverWithSingleTokenDeletion(e)},r.prototype.canRecoverWithSingleTokenInsertion=function(e,t){var i=this;if(!this.canTokenTypeBeInsertedInRecovery(e)||(0,hs.isEmpty)(t))return!1;var n=this.LA(1),s=(0,hs.find)(t,function(o){return i.tokenMatcher(n,o)})!==void 0;return s},r.prototype.canRecoverWithSingleTokenDeletion=function(e){var t=this.tokenMatcher(this.LA(2),e);return t},r.prototype.isInCurrentRuleReSyncSet=function(e){var t=this.getCurrFollowKey(),i=this.getFollowSetFromFollowKey(t);return(0,hs.contains)(i,e)},r.prototype.findReSyncTokenType=function(){for(var e=this.flattenFollowSet(),t=this.LA(1),i=2;;){var n=t.tokenType;if((0,hs.contains)(e,n))return n;t=this.LA(i),i++}},r.prototype.getCurrFollowKey=function(){if(this.RULE_STACK.length===1)return Ki.EOF_FOLLOW_KEY;var e=this.getLastExplicitRuleShortName(),t=this.getLastExplicitRuleOccurrenceIndex(),i=this.getPreviousExplicitRuleShortName();return{ruleName:this.shortRuleNameToFullName(e),idxInCallingRule:t,inRule:this.shortRuleNameToFullName(i)}},r.prototype.buildFullFollowKeyStack=function(){var e=this,t=this.RULE_STACK,i=this.RULE_OCCURRENCE_STACK;return(0,hs.map)(t,function(n,s){return s===0?Ki.EOF_FOLLOW_KEY:{ruleName:e.shortRuleNameToFullName(n),idxInCallingRule:i[s],inRule:e.shortRuleNameToFullName(t[s-1])}})},r.prototype.flattenFollowSet=function(){var e=this,t=(0,hs.map)(this.buildFullFollowKeyStack(),function(i){return e.getFollowSetFromFollowKey(i)});return(0,hs.flatten)(t)},r.prototype.getFollowSetFromFollowKey=function(e){if(e===Ki.EOF_FOLLOW_KEY)return[dy.EOF];var t=e.ruleName+e.idxInCallingRule+oye.IN+e.inRule;return this.resyncFollows[t]},r.prototype.addToResyncTokens=function(e,t){return this.tokenMatcher(e,dy.EOF)||t.push(e),t},r.prototype.reSyncTo=function(e){for(var t=[],i=this.LA(1);this.tokenMatcher(i,e)===!1;)i=this.SKIP_TOKEN(),this.addToResyncTokens(i,t);return(0,hs.dropRight)(t)},r.prototype.attemptInRepetitionRecovery=function(e,t,i,n,s,o,a){},r.prototype.getCurrentGrammarPath=function(e,t){var i=this.getHumanReadableRuleStack(),n=(0,hs.cloneArr)(this.RULE_OCCURRENCE_STACK),s={ruleStack:i,occurrenceStack:n,lastTok:e,lastTokOccurrence:t};return s},r.prototype.getHumanReadableRuleStack=function(){var e=this;return(0,hs.map)(this.RULE_STACK,function(t){return e.shortRuleNameToFullName(t)})},r}();Ki.Recoverable=Aye;function Bq(r,e,t,i,n,s,o){var a=this.getKeyForAutomaticLookahead(i,n),l=this.firstAfterRepMap[a];if(l===void 0){var c=this.getCurrRuleFullName(),u=this.getGAstProductions()[c],g=new s(u,n);l=g.startWalking(),this.firstAfterRepMap[a]=l}var f=l.token,h=l.occurrence,p=l.isEndOfRule;this.RULE_STACK.length===1&&p&&f===void 0&&(f=dy.EOF,h=1),this.shouldInRepetitionRecoveryBeTried(f,h,o)&&this.tryInRepetitionRecovery(r,e,t,f)}Ki.attemptInRepetitionRecovery=Bq});var Cy=w(Jt=>{"use strict";Object.defineProperty(Jt,"__esModule",{value:!0});Jt.getKeyForAutomaticLookahead=Jt.AT_LEAST_ONE_SEP_IDX=Jt.MANY_SEP_IDX=Jt.AT_LEAST_ONE_IDX=Jt.MANY_IDX=Jt.OPTION_IDX=Jt.OR_IDX=Jt.BITS_FOR_ALT_IDX=Jt.BITS_FOR_RULE_IDX=Jt.BITS_FOR_OCCURRENCE_IDX=Jt.BITS_FOR_METHOD_TYPE=void 0;Jt.BITS_FOR_METHOD_TYPE=4;Jt.BITS_FOR_OCCURRENCE_IDX=8;Jt.BITS_FOR_RULE_IDX=12;Jt.BITS_FOR_ALT_IDX=8;Jt.OR_IDX=1<{"use strict";Object.defineProperty(my,"__esModule",{value:!0});my.LooksAhead=void 0;var ka=kd(),ro=Gt(),bq=jn(),Ra=Cy(),Ec=vd(),cye=function(){function r(){}return r.prototype.initLooksAhead=function(e){this.dynamicTokensEnabled=(0,ro.has)(e,"dynamicTokensEnabled")?e.dynamicTokensEnabled:bq.DEFAULT_PARSER_CONFIG.dynamicTokensEnabled,this.maxLookahead=(0,ro.has)(e,"maxLookahead")?e.maxLookahead:bq.DEFAULT_PARSER_CONFIG.maxLookahead,this.lookAheadFuncsCache=(0,ro.isES2015MapSupported)()?new Map:[],(0,ro.isES2015MapSupported)()?(this.getLaFuncFromCache=this.getLaFuncFromMap,this.setLaFuncCache=this.setLaFuncCacheUsingMap):(this.getLaFuncFromCache=this.getLaFuncFromObj,this.setLaFuncCache=this.setLaFuncUsingObj)},r.prototype.preComputeLookaheadFunctions=function(e){var t=this;(0,ro.forEach)(e,function(i){t.TRACE_INIT(i.name+" Rule Lookahead",function(){var n=(0,Ec.collectMethods)(i),s=n.alternation,o=n.repetition,a=n.option,l=n.repetitionMandatory,c=n.repetitionMandatoryWithSeparator,u=n.repetitionWithSeparator;(0,ro.forEach)(s,function(g){var f=g.idx===0?"":g.idx;t.TRACE_INIT(""+(0,Ec.getProductionDslName)(g)+f,function(){var h=(0,ka.buildLookaheadFuncForOr)(g.idx,i,g.maxLookahead||t.maxLookahead,g.hasPredicates,t.dynamicTokensEnabled,t.lookAheadBuilderForAlternatives),p=(0,Ra.getKeyForAutomaticLookahead)(t.fullRuleNameToShort[i.name],Ra.OR_IDX,g.idx);t.setLaFuncCache(p,h)})}),(0,ro.forEach)(o,function(g){t.computeLookaheadFunc(i,g.idx,Ra.MANY_IDX,ka.PROD_TYPE.REPETITION,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(a,function(g){t.computeLookaheadFunc(i,g.idx,Ra.OPTION_IDX,ka.PROD_TYPE.OPTION,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(l,function(g){t.computeLookaheadFunc(i,g.idx,Ra.AT_LEAST_ONE_IDX,ka.PROD_TYPE.REPETITION_MANDATORY,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(c,function(g){t.computeLookaheadFunc(i,g.idx,Ra.AT_LEAST_ONE_SEP_IDX,ka.PROD_TYPE.REPETITION_MANDATORY_WITH_SEPARATOR,g.maxLookahead,(0,Ec.getProductionDslName)(g))}),(0,ro.forEach)(u,function(g){t.computeLookaheadFunc(i,g.idx,Ra.MANY_SEP_IDX,ka.PROD_TYPE.REPETITION_WITH_SEPARATOR,g.maxLookahead,(0,Ec.getProductionDslName)(g))})})})},r.prototype.computeLookaheadFunc=function(e,t,i,n,s,o){var a=this;this.TRACE_INIT(""+o+(t===0?"":t),function(){var l=(0,ka.buildLookaheadFuncForOptionalProd)(t,e,s||a.maxLookahead,a.dynamicTokensEnabled,n,a.lookAheadBuilderForOptional),c=(0,Ra.getKeyForAutomaticLookahead)(a.fullRuleNameToShort[e.name],i,t);a.setLaFuncCache(c,l)})},r.prototype.lookAheadBuilderForOptional=function(e,t,i){return(0,ka.buildSingleAlternativeLookaheadFunction)(e,t,i)},r.prototype.lookAheadBuilderForAlternatives=function(e,t,i,n){return(0,ka.buildAlternativesLookAheadFunc)(e,t,i,n)},r.prototype.getKeyForAutomaticLookahead=function(e,t){var i=this.getLastExplicitRuleShortName();return(0,Ra.getKeyForAutomaticLookahead)(i,e,t)},r.prototype.getLaFuncFromCache=function(e){},r.prototype.getLaFuncFromMap=function(e){return this.lookAheadFuncsCache.get(e)},r.prototype.getLaFuncFromObj=function(e){return this.lookAheadFuncsCache[e]},r.prototype.setLaFuncCache=function(e,t){},r.prototype.setLaFuncCacheUsingMap=function(e,t){this.lookAheadFuncsCache.set(e,t)},r.prototype.setLaFuncUsingObj=function(e,t){this.lookAheadFuncsCache[e]=t},r}();my.LooksAhead=cye});var Sq=w(Lo=>{"use strict";Object.defineProperty(Lo,"__esModule",{value:!0});Lo.addNoneTerminalToCst=Lo.addTerminalToCst=Lo.setNodeLocationFull=Lo.setNodeLocationOnlyOffset=void 0;function uye(r,e){isNaN(r.startOffset)===!0?(r.startOffset=e.startOffset,r.endOffset=e.endOffset):r.endOffset{"use strict";Object.defineProperty(OA,"__esModule",{value:!0});OA.defineNameProp=OA.functionName=OA.classNameFromInstance=void 0;var pye=Gt();function dye(r){return xq(r.constructor)}OA.classNameFromInstance=dye;var vq="name";function xq(r){var e=r.name;return e||"anonymous"}OA.functionName=xq;function Cye(r,e){var t=Object.getOwnPropertyDescriptor(r,vq);return(0,pye.isUndefined)(t)||t.configurable?(Object.defineProperty(r,vq,{enumerable:!1,configurable:!0,writable:!1,value:e}),!0):!1}OA.defineNameProp=Cye});var Fq=w(Si=>{"use strict";Object.defineProperty(Si,"__esModule",{value:!0});Si.validateRedundantMethods=Si.validateMissingCstMethods=Si.validateVisitor=Si.CstVisitorDefinitionError=Si.createBaseVisitorConstructorWithDefaults=Si.createBaseSemanticVisitorConstructor=Si.defaultVisit=void 0;var ps=Gt(),Nd=ox();function Pq(r,e){for(var t=(0,ps.keys)(r),i=t.length,n=0;n: + `+(""+s.join(` + +`).replace(/\n/g,` + `)))}}};return t.prototype=i,t.prototype.constructor=t,t._RULE_NAMES=e,t}Si.createBaseSemanticVisitorConstructor=mye;function Eye(r,e,t){var i=function(){};(0,Nd.defineNameProp)(i,r+"BaseSemanticsWithDefaults");var n=Object.create(t.prototype);return(0,ps.forEach)(e,function(s){n[s]=Pq}),i.prototype=n,i.prototype.constructor=i,i}Si.createBaseVisitorConstructorWithDefaults=Eye;var ax;(function(r){r[r.REDUNDANT_METHOD=0]="REDUNDANT_METHOD",r[r.MISSING_METHOD=1]="MISSING_METHOD"})(ax=Si.CstVisitorDefinitionError||(Si.CstVisitorDefinitionError={}));function Dq(r,e){var t=kq(r,e),i=Rq(r,e);return t.concat(i)}Si.validateVisitor=Dq;function kq(r,e){var t=(0,ps.map)(e,function(i){if(!(0,ps.isFunction)(r[i]))return{msg:"Missing visitor method: <"+i+"> on "+(0,Nd.functionName)(r.constructor)+" CST Visitor.",type:ax.MISSING_METHOD,methodName:i}});return(0,ps.compact)(t)}Si.validateMissingCstMethods=kq;var Iye=["constructor","visit","validateVisitor"];function Rq(r,e){var t=[];for(var i in r)(0,ps.isFunction)(r[i])&&!(0,ps.contains)(Iye,i)&&!(0,ps.contains)(e,i)&&t.push({msg:"Redundant visitor method: <"+i+"> on "+(0,Nd.functionName)(r.constructor)+` CST Visitor +There is no Grammar Rule corresponding to this method's name. +`,type:ax.REDUNDANT_METHOD,methodName:i});return t}Si.validateRedundantMethods=Rq});var Tq=w(Ey=>{"use strict";Object.defineProperty(Ey,"__esModule",{value:!0});Ey.TreeBuilder=void 0;var sf=Sq(),_r=Gt(),Nq=Fq(),yye=jn(),wye=function(){function r(){}return r.prototype.initTreeBuilder=function(e){if(this.CST_STACK=[],this.outputCst=e.outputCst,this.nodeLocationTracking=(0,_r.has)(e,"nodeLocationTracking")?e.nodeLocationTracking:yye.DEFAULT_PARSER_CONFIG.nodeLocationTracking,!this.outputCst)this.cstInvocationStateUpdate=_r.NOOP,this.cstFinallyStateUpdate=_r.NOOP,this.cstPostTerminal=_r.NOOP,this.cstPostNonTerminal=_r.NOOP,this.cstPostRule=_r.NOOP;else if(/full/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=sf.setNodeLocationFull,this.setNodeLocationFromNode=sf.setNodeLocationFull,this.cstPostRule=_r.NOOP,this.setInitialNodeLocation=this.setInitialNodeLocationFullRecovery):(this.setNodeLocationFromToken=_r.NOOP,this.setNodeLocationFromNode=_r.NOOP,this.cstPostRule=this.cstPostRuleFull,this.setInitialNodeLocation=this.setInitialNodeLocationFullRegular);else if(/onlyOffset/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=sf.setNodeLocationOnlyOffset,this.setNodeLocationFromNode=sf.setNodeLocationOnlyOffset,this.cstPostRule=_r.NOOP,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRecovery):(this.setNodeLocationFromToken=_r.NOOP,this.setNodeLocationFromNode=_r.NOOP,this.cstPostRule=this.cstPostRuleOnlyOffset,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRegular);else if(/none/i.test(this.nodeLocationTracking))this.setNodeLocationFromToken=_r.NOOP,this.setNodeLocationFromNode=_r.NOOP,this.cstPostRule=_r.NOOP,this.setInitialNodeLocation=_r.NOOP;else throw Error('Invalid config option: "'+e.nodeLocationTracking+'"')},r.prototype.setInitialNodeLocationOnlyOffsetRecovery=function(e){e.location={startOffset:NaN,endOffset:NaN}},r.prototype.setInitialNodeLocationOnlyOffsetRegular=function(e){e.location={startOffset:this.LA(1).startOffset,endOffset:NaN}},r.prototype.setInitialNodeLocationFullRecovery=function(e){e.location={startOffset:NaN,startLine:NaN,startColumn:NaN,endOffset:NaN,endLine:NaN,endColumn:NaN}},r.prototype.setInitialNodeLocationFullRegular=function(e){var t=this.LA(1);e.location={startOffset:t.startOffset,startLine:t.startLine,startColumn:t.startColumn,endOffset:NaN,endLine:NaN,endColumn:NaN}},r.prototype.cstInvocationStateUpdate=function(e,t){var i={name:e,children:{}};this.setInitialNodeLocation(i),this.CST_STACK.push(i)},r.prototype.cstFinallyStateUpdate=function(){this.CST_STACK.pop()},r.prototype.cstPostRuleFull=function(e){var t=this.LA(0),i=e.location;i.startOffset<=t.startOffset?(i.endOffset=t.endOffset,i.endLine=t.endLine,i.endColumn=t.endColumn):(i.startOffset=NaN,i.startLine=NaN,i.startColumn=NaN)},r.prototype.cstPostRuleOnlyOffset=function(e){var t=this.LA(0),i=e.location;i.startOffset<=t.startOffset?i.endOffset=t.endOffset:i.startOffset=NaN},r.prototype.cstPostTerminal=function(e,t){var i=this.CST_STACK[this.CST_STACK.length-1];(0,sf.addTerminalToCst)(i,t,e),this.setNodeLocationFromToken(i.location,t)},r.prototype.cstPostNonTerminal=function(e,t){var i=this.CST_STACK[this.CST_STACK.length-1];(0,sf.addNoneTerminalToCst)(i,t,e),this.setNodeLocationFromNode(i.location,e.location)},r.prototype.getBaseCstVisitorConstructor=function(){if((0,_r.isUndefined)(this.baseCstVisitorConstructor)){var e=(0,Nq.createBaseSemanticVisitorConstructor)(this.className,(0,_r.keys)(this.gastProductionsCache));return this.baseCstVisitorConstructor=e,e}return this.baseCstVisitorConstructor},r.prototype.getBaseCstVisitorConstructorWithDefaults=function(){if((0,_r.isUndefined)(this.baseCstVisitorWithDefaultsConstructor)){var e=(0,Nq.createBaseVisitorConstructorWithDefaults)(this.className,(0,_r.keys)(this.gastProductionsCache),this.getBaseCstVisitorConstructor());return this.baseCstVisitorWithDefaultsConstructor=e,e}return this.baseCstVisitorWithDefaultsConstructor},r.prototype.getLastExplicitRuleShortName=function(){var e=this.RULE_STACK;return e[e.length-1]},r.prototype.getPreviousExplicitRuleShortName=function(){var e=this.RULE_STACK;return e[e.length-2]},r.prototype.getLastExplicitRuleOccurrenceIndex=function(){var e=this.RULE_OCCURRENCE_STACK;return e[e.length-1]},r}();Ey.TreeBuilder=wye});var Mq=w(Iy=>{"use strict";Object.defineProperty(Iy,"__esModule",{value:!0});Iy.LexerAdapter=void 0;var Lq=jn(),Bye=function(){function r(){}return r.prototype.initLexerAdapter=function(){this.tokVector=[],this.tokVectorLength=0,this.currIdx=-1},Object.defineProperty(r.prototype,"input",{get:function(){return this.tokVector},set:function(e){if(this.selfAnalysisDone!==!0)throw Error("Missing invocation at the end of the Parser's constructor.");this.reset(),this.tokVector=e,this.tokVectorLength=e.length},enumerable:!1,configurable:!0}),r.prototype.SKIP_TOKEN=function(){return this.currIdx<=this.tokVector.length-2?(this.consumeToken(),this.LA(1)):Lq.END_OF_FILE},r.prototype.LA=function(e){var t=this.currIdx+e;return t<0||this.tokVectorLength<=t?Lq.END_OF_FILE:this.tokVector[t]},r.prototype.consumeToken=function(){this.currIdx++},r.prototype.exportLexerState=function(){return this.currIdx},r.prototype.importLexerState=function(e){this.currIdx=e},r.prototype.resetLexerState=function(){this.currIdx=-1},r.prototype.moveToTerminatedState=function(){this.currIdx=this.tokVector.length-1},r.prototype.getLexerPosition=function(){return this.exportLexerState()},r}();Iy.LexerAdapter=Bye});var Kq=w(yy=>{"use strict";Object.defineProperty(yy,"__esModule",{value:!0});yy.RecognizerApi=void 0;var Oq=Gt(),bye=nf(),Ax=jn(),Qye=xd(),Sye=rx(),vye=mn(),xye=function(){function r(){}return r.prototype.ACTION=function(e){return e.call(this)},r.prototype.consume=function(e,t,i){return this.consumeInternal(t,e,i)},r.prototype.subrule=function(e,t,i){return this.subruleInternal(t,e,i)},r.prototype.option=function(e,t){return this.optionInternal(t,e)},r.prototype.or=function(e,t){return this.orInternal(t,e)},r.prototype.many=function(e,t){return this.manyInternal(e,t)},r.prototype.atLeastOne=function(e,t){return this.atLeastOneInternal(e,t)},r.prototype.CONSUME=function(e,t){return this.consumeInternal(e,0,t)},r.prototype.CONSUME1=function(e,t){return this.consumeInternal(e,1,t)},r.prototype.CONSUME2=function(e,t){return this.consumeInternal(e,2,t)},r.prototype.CONSUME3=function(e,t){return this.consumeInternal(e,3,t)},r.prototype.CONSUME4=function(e,t){return this.consumeInternal(e,4,t)},r.prototype.CONSUME5=function(e,t){return this.consumeInternal(e,5,t)},r.prototype.CONSUME6=function(e,t){return this.consumeInternal(e,6,t)},r.prototype.CONSUME7=function(e,t){return this.consumeInternal(e,7,t)},r.prototype.CONSUME8=function(e,t){return this.consumeInternal(e,8,t)},r.prototype.CONSUME9=function(e,t){return this.consumeInternal(e,9,t)},r.prototype.SUBRULE=function(e,t){return this.subruleInternal(e,0,t)},r.prototype.SUBRULE1=function(e,t){return this.subruleInternal(e,1,t)},r.prototype.SUBRULE2=function(e,t){return this.subruleInternal(e,2,t)},r.prototype.SUBRULE3=function(e,t){return this.subruleInternal(e,3,t)},r.prototype.SUBRULE4=function(e,t){return this.subruleInternal(e,4,t)},r.prototype.SUBRULE5=function(e,t){return this.subruleInternal(e,5,t)},r.prototype.SUBRULE6=function(e,t){return this.subruleInternal(e,6,t)},r.prototype.SUBRULE7=function(e,t){return this.subruleInternal(e,7,t)},r.prototype.SUBRULE8=function(e,t){return this.subruleInternal(e,8,t)},r.prototype.SUBRULE9=function(e,t){return this.subruleInternal(e,9,t)},r.prototype.OPTION=function(e){return this.optionInternal(e,0)},r.prototype.OPTION1=function(e){return this.optionInternal(e,1)},r.prototype.OPTION2=function(e){return this.optionInternal(e,2)},r.prototype.OPTION3=function(e){return this.optionInternal(e,3)},r.prototype.OPTION4=function(e){return this.optionInternal(e,4)},r.prototype.OPTION5=function(e){return this.optionInternal(e,5)},r.prototype.OPTION6=function(e){return this.optionInternal(e,6)},r.prototype.OPTION7=function(e){return this.optionInternal(e,7)},r.prototype.OPTION8=function(e){return this.optionInternal(e,8)},r.prototype.OPTION9=function(e){return this.optionInternal(e,9)},r.prototype.OR=function(e){return this.orInternal(e,0)},r.prototype.OR1=function(e){return this.orInternal(e,1)},r.prototype.OR2=function(e){return this.orInternal(e,2)},r.prototype.OR3=function(e){return this.orInternal(e,3)},r.prototype.OR4=function(e){return this.orInternal(e,4)},r.prototype.OR5=function(e){return this.orInternal(e,5)},r.prototype.OR6=function(e){return this.orInternal(e,6)},r.prototype.OR7=function(e){return this.orInternal(e,7)},r.prototype.OR8=function(e){return this.orInternal(e,8)},r.prototype.OR9=function(e){return this.orInternal(e,9)},r.prototype.MANY=function(e){this.manyInternal(0,e)},r.prototype.MANY1=function(e){this.manyInternal(1,e)},r.prototype.MANY2=function(e){this.manyInternal(2,e)},r.prototype.MANY3=function(e){this.manyInternal(3,e)},r.prototype.MANY4=function(e){this.manyInternal(4,e)},r.prototype.MANY5=function(e){this.manyInternal(5,e)},r.prototype.MANY6=function(e){this.manyInternal(6,e)},r.prototype.MANY7=function(e){this.manyInternal(7,e)},r.prototype.MANY8=function(e){this.manyInternal(8,e)},r.prototype.MANY9=function(e){this.manyInternal(9,e)},r.prototype.MANY_SEP=function(e){this.manySepFirstInternal(0,e)},r.prototype.MANY_SEP1=function(e){this.manySepFirstInternal(1,e)},r.prototype.MANY_SEP2=function(e){this.manySepFirstInternal(2,e)},r.prototype.MANY_SEP3=function(e){this.manySepFirstInternal(3,e)},r.prototype.MANY_SEP4=function(e){this.manySepFirstInternal(4,e)},r.prototype.MANY_SEP5=function(e){this.manySepFirstInternal(5,e)},r.prototype.MANY_SEP6=function(e){this.manySepFirstInternal(6,e)},r.prototype.MANY_SEP7=function(e){this.manySepFirstInternal(7,e)},r.prototype.MANY_SEP8=function(e){this.manySepFirstInternal(8,e)},r.prototype.MANY_SEP9=function(e){this.manySepFirstInternal(9,e)},r.prototype.AT_LEAST_ONE=function(e){this.atLeastOneInternal(0,e)},r.prototype.AT_LEAST_ONE1=function(e){return this.atLeastOneInternal(1,e)},r.prototype.AT_LEAST_ONE2=function(e){this.atLeastOneInternal(2,e)},r.prototype.AT_LEAST_ONE3=function(e){this.atLeastOneInternal(3,e)},r.prototype.AT_LEAST_ONE4=function(e){this.atLeastOneInternal(4,e)},r.prototype.AT_LEAST_ONE5=function(e){this.atLeastOneInternal(5,e)},r.prototype.AT_LEAST_ONE6=function(e){this.atLeastOneInternal(6,e)},r.prototype.AT_LEAST_ONE7=function(e){this.atLeastOneInternal(7,e)},r.prototype.AT_LEAST_ONE8=function(e){this.atLeastOneInternal(8,e)},r.prototype.AT_LEAST_ONE9=function(e){this.atLeastOneInternal(9,e)},r.prototype.AT_LEAST_ONE_SEP=function(e){this.atLeastOneSepFirstInternal(0,e)},r.prototype.AT_LEAST_ONE_SEP1=function(e){this.atLeastOneSepFirstInternal(1,e)},r.prototype.AT_LEAST_ONE_SEP2=function(e){this.atLeastOneSepFirstInternal(2,e)},r.prototype.AT_LEAST_ONE_SEP3=function(e){this.atLeastOneSepFirstInternal(3,e)},r.prototype.AT_LEAST_ONE_SEP4=function(e){this.atLeastOneSepFirstInternal(4,e)},r.prototype.AT_LEAST_ONE_SEP5=function(e){this.atLeastOneSepFirstInternal(5,e)},r.prototype.AT_LEAST_ONE_SEP6=function(e){this.atLeastOneSepFirstInternal(6,e)},r.prototype.AT_LEAST_ONE_SEP7=function(e){this.atLeastOneSepFirstInternal(7,e)},r.prototype.AT_LEAST_ONE_SEP8=function(e){this.atLeastOneSepFirstInternal(8,e)},r.prototype.AT_LEAST_ONE_SEP9=function(e){this.atLeastOneSepFirstInternal(9,e)},r.prototype.RULE=function(e,t,i){if(i===void 0&&(i=Ax.DEFAULT_RULE_CONFIG),(0,Oq.contains)(this.definedRulesNames,e)){var n=Qye.defaultGrammarValidatorErrorProvider.buildDuplicateRuleNameError({topLevelRule:e,grammarName:this.className}),s={message:n,type:Ax.ParserDefinitionErrorType.DUPLICATE_RULE_NAME,ruleName:e};this.definitionErrors.push(s)}this.definedRulesNames.push(e);var o=this.defineRule(e,t,i);return this[e]=o,o},r.prototype.OVERRIDE_RULE=function(e,t,i){i===void 0&&(i=Ax.DEFAULT_RULE_CONFIG);var n=[];n=n.concat((0,Sye.validateRuleIsOverridden)(e,this.definedRulesNames,this.className)),this.definitionErrors=this.definitionErrors.concat(n);var s=this.defineRule(e,t,i);return this[e]=s,s},r.prototype.BACKTRACK=function(e,t){return function(){this.isBackTrackingStack.push(1);var i=this.saveRecogState();try{return e.apply(this,t),!0}catch(n){if((0,bye.isRecognitionException)(n))return!1;throw n}finally{this.reloadRecogState(i),this.isBackTrackingStack.pop()}}},r.prototype.getGAstProductions=function(){return this.gastProductionsCache},r.prototype.getSerializedGastProductions=function(){return(0,vye.serializeGrammar)((0,Oq.values)(this.gastProductionsCache))},r}();yy.RecognizerApi=xye});var Yq=w(By=>{"use strict";Object.defineProperty(By,"__esModule",{value:!0});By.RecognizerEngine=void 0;var Pr=Gt(),qn=Cy(),wy=nf(),Uq=kd(),of=Dd(),Hq=jn(),Pye=sx(),Gq=TA(),Td=_g(),Dye=ox(),kye=function(){function r(){}return r.prototype.initRecognizerEngine=function(e,t){if(this.className=(0,Dye.classNameFromInstance)(this),this.shortRuleNameToFull={},this.fullRuleNameToShort={},this.ruleShortNameIdx=256,this.tokenMatcher=Td.tokenStructuredMatcherNoCategories,this.definedRulesNames=[],this.tokensMap={},this.isBackTrackingStack=[],this.RULE_STACK=[],this.RULE_OCCURRENCE_STACK=[],this.gastProductionsCache={},(0,Pr.has)(t,"serializedGrammar"))throw Error(`The Parser's configuration can no longer contain a property. + See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_6-0-0 + For Further details.`);if((0,Pr.isArray)(e)){if((0,Pr.isEmpty)(e))throw Error(`A Token Vocabulary cannot be empty. + Note that the first argument for the parser constructor + is no longer a Token vector (since v4.0).`);if(typeof e[0].startOffset=="number")throw Error(`The Parser constructor no longer accepts a token vector as the first argument. + See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_4-0-0 + For Further details.`)}if((0,Pr.isArray)(e))this.tokensMap=(0,Pr.reduce)(e,function(o,a){return o[a.name]=a,o},{});else if((0,Pr.has)(e,"modes")&&(0,Pr.every)((0,Pr.flatten)((0,Pr.values)(e.modes)),Td.isTokenType)){var i=(0,Pr.flatten)((0,Pr.values)(e.modes)),n=(0,Pr.uniq)(i);this.tokensMap=(0,Pr.reduce)(n,function(o,a){return o[a.name]=a,o},{})}else if((0,Pr.isObject)(e))this.tokensMap=(0,Pr.cloneObj)(e);else throw new Error(" argument must be An Array of Token constructors, A dictionary of Token constructors or an IMultiModeLexerDefinition");this.tokensMap.EOF=Gq.EOF;var s=(0,Pr.every)((0,Pr.values)(e),function(o){return(0,Pr.isEmpty)(o.categoryMatches)});this.tokenMatcher=s?Td.tokenStructuredMatcherNoCategories:Td.tokenStructuredMatcher,(0,Td.augmentTokenTypes)((0,Pr.values)(this.tokensMap))},r.prototype.defineRule=function(e,t,i){if(this.selfAnalysisDone)throw Error("Grammar rule <"+e+`> may not be defined after the 'performSelfAnalysis' method has been called' +Make sure that all grammar rule definitions are done before 'performSelfAnalysis' is called.`);var n=(0,Pr.has)(i,"resyncEnabled")?i.resyncEnabled:Hq.DEFAULT_RULE_CONFIG.resyncEnabled,s=(0,Pr.has)(i,"recoveryValueFunc")?i.recoveryValueFunc:Hq.DEFAULT_RULE_CONFIG.recoveryValueFunc,o=this.ruleShortNameIdx<t},r.prototype.orInternal=function(e,t){var i=this.getKeyForAutomaticLookahead(qn.OR_IDX,t),n=(0,Pr.isArray)(e)?e:e.DEF,s=this.getLaFuncFromCache(i),o=s.call(this,n);if(o!==void 0){var a=n[o];return a.ALT.call(this)}this.raiseNoAltException(t,e.ERR_MSG)},r.prototype.ruleFinallyStateUpdate=function(){if(this.RULE_STACK.pop(),this.RULE_OCCURRENCE_STACK.pop(),this.cstFinallyStateUpdate(),this.RULE_STACK.length===0&&this.isAtEndOfInput()===!1){var e=this.LA(1),t=this.errorMessageProvider.buildNotAllInputParsedMessage({firstRedundant:e,ruleName:this.getCurrRuleFullName()});this.SAVE_ERROR(new wy.NotAllInputParsedException(t,e))}},r.prototype.subruleInternal=function(e,t,i){var n;try{var s=i!==void 0?i.ARGS:void 0;return n=e.call(this,t,s),this.cstPostNonTerminal(n,i!==void 0&&i.LABEL!==void 0?i.LABEL:e.ruleName),n}catch(o){this.subruleInternalError(o,i,e.ruleName)}},r.prototype.subruleInternalError=function(e,t,i){throw(0,wy.isRecognitionException)(e)&&e.partialCstResult!==void 0&&(this.cstPostNonTerminal(e.partialCstResult,t!==void 0&&t.LABEL!==void 0?t.LABEL:i),delete e.partialCstResult),e},r.prototype.consumeInternal=function(e,t,i){var n;try{var s=this.LA(1);this.tokenMatcher(s,e)===!0?(this.consumeToken(),n=s):this.consumeInternalError(e,s,i)}catch(o){n=this.consumeInternalRecovery(e,t,o)}return this.cstPostTerminal(i!==void 0&&i.LABEL!==void 0?i.LABEL:e.name,n),n},r.prototype.consumeInternalError=function(e,t,i){var n,s=this.LA(0);throw i!==void 0&&i.ERR_MSG?n=i.ERR_MSG:n=this.errorMessageProvider.buildMismatchTokenMessage({expected:e,actual:t,previous:s,ruleName:this.getCurrRuleFullName()}),this.SAVE_ERROR(new wy.MismatchedTokenException(n,t,s))},r.prototype.consumeInternalRecovery=function(e,t,i){if(this.recoveryEnabled&&i.name==="MismatchedTokenException"&&!this.isBackTracking()){var n=this.getFollowsForInRuleRecovery(e,t);try{return this.tryInRuleRecovery(e,n)}catch(s){throw s.name===Pye.IN_RULE_RECOVERY_EXCEPTION?i:s}}else throw i},r.prototype.saveRecogState=function(){var e=this.errors,t=(0,Pr.cloneArr)(this.RULE_STACK);return{errors:e,lexerState:this.exportLexerState(),RULE_STACK:t,CST_STACK:this.CST_STACK}},r.prototype.reloadRecogState=function(e){this.errors=e.errors,this.importLexerState(e.lexerState),this.RULE_STACK=e.RULE_STACK},r.prototype.ruleInvocationStateUpdate=function(e,t,i){this.RULE_OCCURRENCE_STACK.push(i),this.RULE_STACK.push(e),this.cstInvocationStateUpdate(t,e)},r.prototype.isBackTracking=function(){return this.isBackTrackingStack.length!==0},r.prototype.getCurrRuleFullName=function(){var e=this.getLastExplicitRuleShortName();return this.shortRuleNameToFull[e]},r.prototype.shortRuleNameToFullName=function(e){return this.shortRuleNameToFull[e]},r.prototype.isAtEndOfInput=function(){return this.tokenMatcher(this.LA(1),Gq.EOF)},r.prototype.reset=function(){this.resetLexerState(),this.isBackTrackingStack=[],this.errors=[],this.RULE_STACK=[],this.CST_STACK=[],this.RULE_OCCURRENCE_STACK=[]},r}();By.RecognizerEngine=kye});var qq=w(by=>{"use strict";Object.defineProperty(by,"__esModule",{value:!0});by.ErrorHandler=void 0;var lx=nf(),cx=Gt(),jq=kd(),Rye=jn(),Fye=function(){function r(){}return r.prototype.initErrorHandler=function(e){this._errors=[],this.errorMessageProvider=(0,cx.has)(e,"errorMessageProvider")?e.errorMessageProvider:Rye.DEFAULT_PARSER_CONFIG.errorMessageProvider},r.prototype.SAVE_ERROR=function(e){if((0,lx.isRecognitionException)(e))return e.context={ruleStack:this.getHumanReadableRuleStack(),ruleOccurrenceStack:(0,cx.cloneArr)(this.RULE_OCCURRENCE_STACK)},this._errors.push(e),e;throw Error("Trying to save an Error which is not a RecognitionException")},Object.defineProperty(r.prototype,"errors",{get:function(){return(0,cx.cloneArr)(this._errors)},set:function(e){this._errors=e},enumerable:!1,configurable:!0}),r.prototype.raiseEarlyExitException=function(e,t,i){for(var n=this.getCurrRuleFullName(),s=this.getGAstProductions()[n],o=(0,jq.getLookaheadPathsForOptionalProd)(e,s,t,this.maxLookahead),a=o[0],l=[],c=1;c<=this.maxLookahead;c++)l.push(this.LA(c));var u=this.errorMessageProvider.buildEarlyExitMessage({expectedIterationPaths:a,actual:l,previous:this.LA(0),customUserDescription:i,ruleName:n});throw this.SAVE_ERROR(new lx.EarlyExitException(u,this.LA(1),this.LA(0)))},r.prototype.raiseNoAltException=function(e,t){for(var i=this.getCurrRuleFullName(),n=this.getGAstProductions()[i],s=(0,jq.getLookaheadPathsForOr)(e,n,this.maxLookahead),o=[],a=1;a<=this.maxLookahead;a++)o.push(this.LA(a));var l=this.LA(0),c=this.errorMessageProvider.buildNoViableAltMessage({expectedPathsPerAlt:s,actual:o,previous:l,customUserDescription:t,ruleName:this.getCurrRuleFullName()});throw this.SAVE_ERROR(new lx.NoViableAltException(c,this.LA(1),l))},r}();by.ErrorHandler=Fye});var zq=w(Qy=>{"use strict";Object.defineProperty(Qy,"__esModule",{value:!0});Qy.ContentAssist=void 0;var Jq=Dd(),Wq=Gt(),Nye=function(){function r(){}return r.prototype.initContentAssist=function(){},r.prototype.computeContentAssist=function(e,t){var i=this.gastProductionsCache[e];if((0,Wq.isUndefined)(i))throw Error("Rule ->"+e+"<- does not exist in this grammar.");return(0,Jq.nextPossibleTokensAfter)([i],t,this.tokenMatcher,this.maxLookahead)},r.prototype.getNextPossibleTokenTypes=function(e){var t=(0,Wq.first)(e.ruleStack),i=this.getGAstProductions(),n=i[t],s=new Jq.NextAfterTokenWalker(n,e).startWalking();return s},r}();Qy.ContentAssist=Nye});var rJ=w(xy=>{"use strict";Object.defineProperty(xy,"__esModule",{value:!0});xy.GastRecorder=void 0;var yn=Gt(),Mo=mn(),Tye=Bd(),_q=_g(),$q=TA(),Lye=jn(),Mye=Cy(),vy={description:"This Object indicates the Parser is during Recording Phase"};Object.freeze(vy);var Vq=!0,Xq=Math.pow(2,Mye.BITS_FOR_OCCURRENCE_IDX)-1,eJ=(0,$q.createToken)({name:"RECORDING_PHASE_TOKEN",pattern:Tye.Lexer.NA});(0,_q.augmentTokenTypes)([eJ]);var tJ=(0,$q.createTokenInstance)(eJ,`This IToken indicates the Parser is in Recording Phase + See: https://chevrotain.io/docs/guide/internals.html#grammar-recording for details`,-1,-1,-1,-1,-1,-1);Object.freeze(tJ);var Oye={name:`This CSTNode indicates the Parser is in Recording Phase + See: https://chevrotain.io/docs/guide/internals.html#grammar-recording for details`,children:{}},Kye=function(){function r(){}return r.prototype.initGastRecorder=function(e){this.recordingProdStack=[],this.RECORDING_PHASE=!1},r.prototype.enableRecording=function(){var e=this;this.RECORDING_PHASE=!0,this.TRACE_INIT("Enable Recording",function(){for(var t=function(n){var s=n>0?n:"";e["CONSUME"+s]=function(o,a){return this.consumeInternalRecord(o,n,a)},e["SUBRULE"+s]=function(o,a){return this.subruleInternalRecord(o,n,a)},e["OPTION"+s]=function(o){return this.optionInternalRecord(o,n)},e["OR"+s]=function(o){return this.orInternalRecord(o,n)},e["MANY"+s]=function(o){this.manyInternalRecord(n,o)},e["MANY_SEP"+s]=function(o){this.manySepFirstInternalRecord(n,o)},e["AT_LEAST_ONE"+s]=function(o){this.atLeastOneInternalRecord(n,o)},e["AT_LEAST_ONE_SEP"+s]=function(o){this.atLeastOneSepFirstInternalRecord(n,o)}},i=0;i<10;i++)t(i);e.consume=function(n,s,o){return this.consumeInternalRecord(s,n,o)},e.subrule=function(n,s,o){return this.subruleInternalRecord(s,n,o)},e.option=function(n,s){return this.optionInternalRecord(s,n)},e.or=function(n,s){return this.orInternalRecord(s,n)},e.many=function(n,s){this.manyInternalRecord(n,s)},e.atLeastOne=function(n,s){this.atLeastOneInternalRecord(n,s)},e.ACTION=e.ACTION_RECORD,e.BACKTRACK=e.BACKTRACK_RECORD,e.LA=e.LA_RECORD})},r.prototype.disableRecording=function(){var e=this;this.RECORDING_PHASE=!1,this.TRACE_INIT("Deleting Recording methods",function(){for(var t=0;t<10;t++){var i=t>0?t:"";delete e["CONSUME"+i],delete e["SUBRULE"+i],delete e["OPTION"+i],delete e["OR"+i],delete e["MANY"+i],delete e["MANY_SEP"+i],delete e["AT_LEAST_ONE"+i],delete e["AT_LEAST_ONE_SEP"+i]}delete e.consume,delete e.subrule,delete e.option,delete e.or,delete e.many,delete e.atLeastOne,delete e.ACTION,delete e.BACKTRACK,delete e.LA})},r.prototype.ACTION_RECORD=function(e){},r.prototype.BACKTRACK_RECORD=function(e,t){return function(){return!0}},r.prototype.LA_RECORD=function(e){return Lye.END_OF_FILE},r.prototype.topLevelRuleRecord=function(e,t){try{var i=new Mo.Rule({definition:[],name:e});return i.name=e,this.recordingProdStack.push(i),t.call(this),this.recordingProdStack.pop(),i}catch(n){if(n.KNOWN_RECORDER_ERROR!==!0)try{n.message=n.message+` + This error was thrown during the "grammar recording phase" For more info see: + https://chevrotain.io/docs/guide/internals.html#grammar-recording`}catch{throw n}throw n}},r.prototype.optionInternalRecord=function(e,t){return Ld.call(this,Mo.Option,e,t)},r.prototype.atLeastOneInternalRecord=function(e,t){Ld.call(this,Mo.RepetitionMandatory,t,e)},r.prototype.atLeastOneSepFirstInternalRecord=function(e,t){Ld.call(this,Mo.RepetitionMandatoryWithSeparator,t,e,Vq)},r.prototype.manyInternalRecord=function(e,t){Ld.call(this,Mo.Repetition,t,e)},r.prototype.manySepFirstInternalRecord=function(e,t){Ld.call(this,Mo.RepetitionWithSeparator,t,e,Vq)},r.prototype.orInternalRecord=function(e,t){return Uye.call(this,e,t)},r.prototype.subruleInternalRecord=function(e,t,i){if(Sy(t),!e||(0,yn.has)(e,"ruleName")===!1){var n=new Error(" argument is invalid"+(" expecting a Parser method reference but got: <"+JSON.stringify(e)+">")+(` + inside top level rule: <`+this.recordingProdStack[0].name+">"));throw n.KNOWN_RECORDER_ERROR=!0,n}var s=(0,yn.peek)(this.recordingProdStack),o=e.ruleName,a=new Mo.NonTerminal({idx:t,nonTerminalName:o,label:i==null?void 0:i.LABEL,referencedRule:void 0});return s.definition.push(a),this.outputCst?Oye:vy},r.prototype.consumeInternalRecord=function(e,t,i){if(Sy(t),!(0,_q.hasShortKeyProperty)(e)){var n=new Error(" argument is invalid"+(" expecting a TokenType reference but got: <"+JSON.stringify(e)+">")+(` + inside top level rule: <`+this.recordingProdStack[0].name+">"));throw n.KNOWN_RECORDER_ERROR=!0,n}var s=(0,yn.peek)(this.recordingProdStack),o=new Mo.Terminal({idx:t,terminalType:e,label:i==null?void 0:i.LABEL});return s.definition.push(o),tJ},r}();xy.GastRecorder=Kye;function Ld(r,e,t,i){i===void 0&&(i=!1),Sy(t);var n=(0,yn.peek)(this.recordingProdStack),s=(0,yn.isFunction)(e)?e:e.DEF,o=new r({definition:[],idx:t});return i&&(o.separator=e.SEP),(0,yn.has)(e,"MAX_LOOKAHEAD")&&(o.maxLookahead=e.MAX_LOOKAHEAD),this.recordingProdStack.push(o),s.call(this),n.definition.push(o),this.recordingProdStack.pop(),vy}function Uye(r,e){var t=this;Sy(e);var i=(0,yn.peek)(this.recordingProdStack),n=(0,yn.isArray)(r)===!1,s=n===!1?r:r.DEF,o=new Mo.Alternation({definition:[],idx:e,ignoreAmbiguities:n&&r.IGNORE_AMBIGUITIES===!0});(0,yn.has)(r,"MAX_LOOKAHEAD")&&(o.maxLookahead=r.MAX_LOOKAHEAD);var a=(0,yn.some)(s,function(l){return(0,yn.isFunction)(l.GATE)});return o.hasPredicates=a,i.definition.push(o),(0,yn.forEach)(s,function(l){var c=new Mo.Alternative({definition:[]});o.definition.push(c),(0,yn.has)(l,"IGNORE_AMBIGUITIES")?c.ignoreAmbiguities=l.IGNORE_AMBIGUITIES:(0,yn.has)(l,"GATE")&&(c.ignoreAmbiguities=!0),t.recordingProdStack.push(c),l.ALT.call(t),t.recordingProdStack.pop()}),vy}function Zq(r){return r===0?"":""+r}function Sy(r){if(r<0||r>Xq){var e=new Error("Invalid DSL Method idx value: <"+r+`> + `+("Idx value must be a none negative value smaller than "+(Xq+1)));throw e.KNOWN_RECORDER_ERROR=!0,e}}});var nJ=w(Py=>{"use strict";Object.defineProperty(Py,"__esModule",{value:!0});Py.PerformanceTracer=void 0;var iJ=Gt(),Hye=jn(),Gye=function(){function r(){}return r.prototype.initPerformanceTracer=function(e){if((0,iJ.has)(e,"traceInitPerf")){var t=e.traceInitPerf,i=typeof t=="number";this.traceInitMaxIdent=i?t:1/0,this.traceInitPerf=i?t>0:t}else this.traceInitMaxIdent=0,this.traceInitPerf=Hye.DEFAULT_PARSER_CONFIG.traceInitPerf;this.traceInitIndent=-1},r.prototype.TRACE_INIT=function(e,t){if(this.traceInitPerf===!0){this.traceInitIndent++;var i=new Array(this.traceInitIndent+1).join(" ");this.traceInitIndent <"+e+">");var n=(0,iJ.timer)(t),s=n.time,o=n.value,a=s>10?console.warn:console.log;return this.traceInitIndent time: "+s+"ms"),this.traceInitIndent--,o}else return t()},r}();Py.PerformanceTracer=Gye});var sJ=w(Dy=>{"use strict";Object.defineProperty(Dy,"__esModule",{value:!0});Dy.applyMixins=void 0;function Yye(r,e){e.forEach(function(t){var i=t.prototype;Object.getOwnPropertyNames(i).forEach(function(n){if(n!=="constructor"){var s=Object.getOwnPropertyDescriptor(i,n);s&&(s.get||s.set)?Object.defineProperty(r.prototype,n,s):r.prototype[n]=t.prototype[n]}})})}Dy.applyMixins=Yye});var jn=w(dr=>{"use strict";var AJ=dr&&dr.__extends||function(){var r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(i,n){i.__proto__=n}||function(i,n){for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(i[s]=n[s])},r(e,t)};return function(e,t){if(typeof t!="function"&&t!==null)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");r(e,t);function i(){this.constructor=e}e.prototype=t===null?Object.create(t):(i.prototype=t.prototype,new i)}}();Object.defineProperty(dr,"__esModule",{value:!0});dr.EmbeddedActionsParser=dr.CstParser=dr.Parser=dr.EMPTY_ALT=dr.ParserDefinitionErrorType=dr.DEFAULT_RULE_CONFIG=dr.DEFAULT_PARSER_CONFIG=dr.END_OF_FILE=void 0;var en=Gt(),jye=qj(),oJ=TA(),lJ=xd(),aJ=Cq(),qye=sx(),Jye=Qq(),Wye=Tq(),zye=Mq(),Vye=Kq(),Xye=Yq(),Zye=qq(),_ye=zq(),$ye=rJ(),ewe=nJ(),twe=sJ();dr.END_OF_FILE=(0,oJ.createTokenInstance)(oJ.EOF,"",NaN,NaN,NaN,NaN,NaN,NaN);Object.freeze(dr.END_OF_FILE);dr.DEFAULT_PARSER_CONFIG=Object.freeze({recoveryEnabled:!1,maxLookahead:3,dynamicTokensEnabled:!1,outputCst:!0,errorMessageProvider:lJ.defaultParserErrorProvider,nodeLocationTracking:"none",traceInitPerf:!1,skipValidations:!1});dr.DEFAULT_RULE_CONFIG=Object.freeze({recoveryValueFunc:function(){},resyncEnabled:!0});var rwe;(function(r){r[r.INVALID_RULE_NAME=0]="INVALID_RULE_NAME",r[r.DUPLICATE_RULE_NAME=1]="DUPLICATE_RULE_NAME",r[r.INVALID_RULE_OVERRIDE=2]="INVALID_RULE_OVERRIDE",r[r.DUPLICATE_PRODUCTIONS=3]="DUPLICATE_PRODUCTIONS",r[r.UNRESOLVED_SUBRULE_REF=4]="UNRESOLVED_SUBRULE_REF",r[r.LEFT_RECURSION=5]="LEFT_RECURSION",r[r.NONE_LAST_EMPTY_ALT=6]="NONE_LAST_EMPTY_ALT",r[r.AMBIGUOUS_ALTS=7]="AMBIGUOUS_ALTS",r[r.CONFLICT_TOKENS_RULES_NAMESPACE=8]="CONFLICT_TOKENS_RULES_NAMESPACE",r[r.INVALID_TOKEN_NAME=9]="INVALID_TOKEN_NAME",r[r.NO_NON_EMPTY_LOOKAHEAD=10]="NO_NON_EMPTY_LOOKAHEAD",r[r.AMBIGUOUS_PREFIX_ALTS=11]="AMBIGUOUS_PREFIX_ALTS",r[r.TOO_MANY_ALTS=12]="TOO_MANY_ALTS"})(rwe=dr.ParserDefinitionErrorType||(dr.ParserDefinitionErrorType={}));function iwe(r){return r===void 0&&(r=void 0),function(){return r}}dr.EMPTY_ALT=iwe;var ky=function(){function r(e,t){this.definitionErrors=[],this.selfAnalysisDone=!1;var i=this;if(i.initErrorHandler(t),i.initLexerAdapter(),i.initLooksAhead(t),i.initRecognizerEngine(e,t),i.initRecoverable(t),i.initTreeBuilder(t),i.initContentAssist(),i.initGastRecorder(t),i.initPerformanceTracer(t),(0,en.has)(t,"ignoredIssues"))throw new Error(`The IParserConfig property has been deprecated. + Please use the flag on the relevant DSL method instead. + See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#IGNORING_AMBIGUITIES + For further details.`);this.skipValidations=(0,en.has)(t,"skipValidations")?t.skipValidations:dr.DEFAULT_PARSER_CONFIG.skipValidations}return r.performSelfAnalysis=function(e){throw Error("The **static** `performSelfAnalysis` method has been deprecated. \nUse the **instance** method with the same name instead.")},r.prototype.performSelfAnalysis=function(){var e=this;this.TRACE_INIT("performSelfAnalysis",function(){var t;e.selfAnalysisDone=!0;var i=e.className;e.TRACE_INIT("toFastProps",function(){(0,en.toFastProperties)(e)}),e.TRACE_INIT("Grammar Recording",function(){try{e.enableRecording(),(0,en.forEach)(e.definedRulesNames,function(s){var o=e[s],a=o.originalGrammarAction,l=void 0;e.TRACE_INIT(s+" Rule",function(){l=e.topLevelRuleRecord(s,a)}),e.gastProductionsCache[s]=l})}finally{e.disableRecording()}});var n=[];if(e.TRACE_INIT("Grammar Resolving",function(){n=(0,aJ.resolveGrammar)({rules:(0,en.values)(e.gastProductionsCache)}),e.definitionErrors=e.definitionErrors.concat(n)}),e.TRACE_INIT("Grammar Validations",function(){if((0,en.isEmpty)(n)&&e.skipValidations===!1){var s=(0,aJ.validateGrammar)({rules:(0,en.values)(e.gastProductionsCache),maxLookahead:e.maxLookahead,tokenTypes:(0,en.values)(e.tokensMap),errMsgProvider:lJ.defaultGrammarValidatorErrorProvider,grammarName:i});e.definitionErrors=e.definitionErrors.concat(s)}}),(0,en.isEmpty)(e.definitionErrors)&&(e.recoveryEnabled&&e.TRACE_INIT("computeAllProdsFollows",function(){var s=(0,jye.computeAllProdsFollows)((0,en.values)(e.gastProductionsCache));e.resyncFollows=s}),e.TRACE_INIT("ComputeLookaheadFunctions",function(){e.preComputeLookaheadFunctions((0,en.values)(e.gastProductionsCache))})),!r.DEFER_DEFINITION_ERRORS_HANDLING&&!(0,en.isEmpty)(e.definitionErrors))throw t=(0,en.map)(e.definitionErrors,function(s){return s.message}),new Error(`Parser Definition Errors detected: + `+t.join(` +------------------------------- +`))})},r.DEFER_DEFINITION_ERRORS_HANDLING=!1,r}();dr.Parser=ky;(0,twe.applyMixins)(ky,[qye.Recoverable,Jye.LooksAhead,Wye.TreeBuilder,zye.LexerAdapter,Xye.RecognizerEngine,Vye.RecognizerApi,Zye.ErrorHandler,_ye.ContentAssist,$ye.GastRecorder,ewe.PerformanceTracer]);var nwe=function(r){AJ(e,r);function e(t,i){i===void 0&&(i=dr.DEFAULT_PARSER_CONFIG);var n=this,s=(0,en.cloneObj)(i);return s.outputCst=!0,n=r.call(this,t,s)||this,n}return e}(ky);dr.CstParser=nwe;var swe=function(r){AJ(e,r);function e(t,i){i===void 0&&(i=dr.DEFAULT_PARSER_CONFIG);var n=this,s=(0,en.cloneObj)(i);return s.outputCst=!1,n=r.call(this,t,s)||this,n}return e}(ky);dr.EmbeddedActionsParser=swe});var uJ=w(Ry=>{"use strict";Object.defineProperty(Ry,"__esModule",{value:!0});Ry.createSyntaxDiagramsCode=void 0;var cJ=Dv();function owe(r,e){var t=e===void 0?{}:e,i=t.resourceBase,n=i===void 0?"https://unpkg.com/chevrotain@"+cJ.VERSION+"/diagrams/":i,s=t.css,o=s===void 0?"https://unpkg.com/chevrotain@"+cJ.VERSION+"/diagrams/diagrams.css":s,a=` + + + + + +`,l=` + +`,c=` + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It _could_ be a beautiful UI... Depending on which universe you live in. In any case, we're using some scary CSS to make two boxes that will show cool things on the screen. + +As for the JS, real madmen could just `console.log` everything, but let's say we want to see things happening (the true initial purpose of JS... right?). Here's some boilerplate for that. Just paste it in `index.js`: + +```js +const show = (id, content) => { + const container = document.getElementById(id); + container.appendChild(document.createTextNode(content)); + container.appendChild(document.createElement("br")); +}; + +document.getElementById("submit").addEventListener("click", async () => { + try { + // noir goes here + } catch { + show("logs", "Oh 💔"); + } +}); + +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── src + └── main.nr + Nargo.toml + index.js + package.json + index.html + ...etc +``` + +::: + +## Compile compile compile + +Finally we're up for something cool. But before we can execute a Noir program, we need to compile it into ACIR: an abstract representation. Here's where `noir_wasm` comes in. + +`noir_wasm` expects a filesystem so it can resolve dependencies. While we could use the `public` folder, let's just import those using the nice `?url` syntax provided by vite. At the top of the file: + +```js +import { compile, createFileManager } from "@noir-lang/noir_wasm" + +import main from "./circuit/src/main.nr?url"; +import nargoToml from "./circuit/Nargo.toml?url"; +``` + +Compiling on the browser is common enough that `createFileManager` already gives us a nice in-memory filesystem we can use. So all we need to compile is fetching these files, writing them to our filesystem, and compile. Add this function: + +```js +export async function getCircuit() { + const fm = createFileManager("/"); + const { body } = await fetch(main); + const { body: nargoTomlBody } = await fetch(nargoToml); + + fm.writeFile("./src/main.nr", body); + fm.writeFile("./Nargo.toml", nargoTomlBody); + return await compile(fm); +} +``` + +:::tip + +As you can imagine, with `node` it's all conveniently easier since you get native access to `fs`... + +::: + +## Some more JS + +We're starting with the good stuff now. We want to execute our circuit to get the witness, and then feed that witness to Barretenberg. Luckily, both packages are quite easy to work with. Let's import them at the top of the file: + +```js +import { UltraHonkBackend } from '@aztec/bb.js'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const { program } = await getCircuit(); +const noir = new Noir(program); +const backend = new UltraHonkBackend(program.bytecode); +// } +``` + +:::warning + +WASMs are not always easy to work with. In our case, `vite` likes serving them with the wrong MIME type. There are different fixes but we found the easiest one is just YOLO instantiating the WASMs manually. Paste this at the top of the file, just below the other imports, and it will work just fine: + +```js +import initNoirC from "@noir-lang/noirc_abi"; +import initACVM from "@noir-lang/acvm_js"; +import acvm from "@noir-lang/acvm_js/web/acvm_js_bg.wasm?url"; +import noirc from "@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm?url"; +await Promise.all([initACVM(fetch(acvm)), initNoirC(fetch(noirc))]); +``` + +::: + +## Executing and proving + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Inside our `try` block, let's just grab that input and get its value. Noir will gladly execute it, and give us a witness: + +```js +const age = document.getElementById("age").value; +show("logs", "Generating witness... ⏳"); +const { witness } = await noir.execute({ age }); +show("logs", "Generated witness... ✅"); + +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +show("logs", "Generating proof... ⏳"); +const proof = await backend.generateProof(witness); +show("logs", "Generated proof... ✅"); +show("results", proof.proof); +``` + +Our program is technically **done** . You're probably eager to see stuff happening! To serve this in a convenient way, we can use a bundler like `vite` by creating a `vite.config.js` file: + +```bash +touch vite.config.js +``` + +`vite` helps us with a little catch: `bb.js` in particular uses top-level awaits which aren't supported everywhere. So we can add this to the `vite.config.js` to make the bundler optimize them: + +```js +export default { optimizeDeps: { esbuildOptions: { target: "esnext" } } }; +``` + +This should be enough for vite. We don't even need to install it, just run: + +```bash +bunx vite +``` + +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. + +![Noir Webapp UI](@site/static/img/tutorials/noirjs_webapp/webapp1.png) + +Now, our circuit requires a private input `fn main(age: u8)`, and fails if it is less than 18. Let's see if it works. Submit any number above 18 (as long as it fits in 8 bits) and 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 +show('logs', 'Verifying proof... ⌛'); +const isValid = await backend.verifyProof(proof); +show("logs", `Proof is ${isValid ? "valid" : "invalid"}... ✅`); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## Next steps + +At this point, you have a working ZK app that works on the browser. Actually, it works on a mobile phone too! + +If you want to continue learning by doing, here are some challenges for you: + +- Install [nargo](https://noir-lang.org/docs/getting_started/noir_installation) and write [Noir tests](../tooling/testing) +- Change the circuit to accept a [public input](../noir/concepts/data_types/#private--public-types) as the cutoff age. It could be different depending on the purpose, for example! +- Enjoy Noir's Rust-like syntax and write a struct `Country` that implements a trait `MinAge` with a method `get_min_age`. Then, make a struct `Person` have an `u8` as its age and a country of type `Country`. You can pass a `person` in JS just like a JSON object `person: { age, country: { min_age: 18 }}` + +The world is your stage, just have fun with ZK! 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. + +Check out other starters, tools, or just cool projects in the [awesome noir repository](https://github.com/noir-lang/awesome-noir). diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts new file mode 100644 index 00000000000..eee4e7f8236 --- /dev/null +++ b/docs/docusaurus.config.ts @@ -0,0 +1,219 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +import type { Config } from '@docusaurus/types'; + +const { themes } = require('prism-react-renderer'); +const lightTheme = themes.github; +const darkTheme = themes.dracula; + +import math from 'remark-math'; +import katex from 'rehype-katex'; + +export default { + title: 'Noir Documentation', + tagline: 'The Universal ZK Circuit Language', + favicon: 'img/favicon.ico', + url: 'https://noir-lang.org', + baseUrl: '/', + onBrokenLinks: 'throw', + onBrokenMarkdownLinks: process.env.ENV === 'dev' ? 'warn' : 'throw', + i18n: { + defaultLocale: 'en', + locales: ['en'], + }, + + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + path: process.env.ENV === 'dev' ? 'docs' : 'processed-docs', + sidebarPath: './sidebars.js', + routeBasePath: '/docs', + remarkPlugins: [math], + rehypePlugins: [katex], + versions: { + current: { + label: 'dev', + path: 'dev', + }, + }, + editUrl: ({ versionDocsDirPath, docPath }) => + `https://github.com/noir-lang/noir/edit/master/docs/${versionDocsDirPath.replace('processed-docs', 'docs')}/${docPath}`, + }, + blog: false, + theme: { + customCss: ['./src/css/custom.css', './src/css/sidebar.css'], + }, + }, + ], + ], + customFields: { + MATOMO_ENV: process.env.ENV, + }, + themeConfig: { + colorMode: { + respectPrefersColorScheme: true, + }, + navbar: { + logo: { + alt: 'Noir Logo', + src: 'img/logoDark.svg', + srcDark: 'img/logo.svg', + href: '/', + }, + items: [ + { + href: 'https://github.com/noir-lang/noir/tree/master/docs', + label: 'GitHub', + position: 'right', + }, + { + type: 'docsVersionDropdown', + position: 'left', + dropdownActiveClassDisabled: true, + }, + ], + }, + metadata: [ + { + name: 'Noir', + content: 'noir, programming, language, documentation, zk, zero-knowledge, l2, crypto, layer2, ethereum', + }, + ], + footer: { + style: 'dark', + links: [ + { + title: 'Community', + items: [ + { + label: 'Noir Forum', + href: 'https://discourse.aztec.network/c/noir/7', + }, + { + label: 'Twitter', + href: 'https://twitter.com/NoirLang', + }, + { + label: 'Discord', + href: 'https://discord.gg/JtqzkdeQ6G', + }, + ], + }, + { + title: 'Code', + items: [ + { + label: 'Noir GitHub', + href: 'https://github.com/noir-lang', + }, + { + label: 'Docs GitHub', + href: 'https://github.com/noir-lang/noir/tree/master/docs', + }, + ], + }, + ], + copyright: `Noir will be dual licensed under MIT/Apache (Version 2.0).`, + }, + prism: { + theme: lightTheme, + darkTheme: darkTheme, + additionalLanguages: ['rust', 'powershell', 'solidity', 'toml', 'json', 'bash', 'docker'], + }, + stylesheets: [ + { + href: 'https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css', + type: 'text/css', + integrity: 'sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM', + crossorigin: 'anonymous', + }, + ], + algolia: { + // The application ID provided by Algolia + appId: '97APAVUL6H', + + // Public API key: it is safe to commit it + apiKey: 'b9b94d2f1c58f7d509f0bc1f13b381fb', + contextualSearch: true, + indexName: 'noir-lang', + }, + }, + plugins: [ + () => ({ + name: 'resolve-react', + configureWebpack() { + return { + optimization: { + innerGraph: false, + }, + }; + }, + }), + [ + 'docusaurus-plugin-typedoc', + { + id: 'noir_js', + entryPoints: ['../tooling/noir_js/src/index.ts'], + tsconfig: '../tooling/noir_js/tsconfig.json', + entryPointStrategy: 'resolve', + out: 'processed-docs/reference/NoirJS/noir_js', + plugin: ['typedoc-plugin-markdown'], + name: 'noir_js', + disableSources: true, + excludePrivate: true, + skipErrorChecking: true, + sidebar: { + filteredIds: ['reference/NoirJS/noir_js/index'], + }, + readme: 'none', + hidePageHeader: true, + hideBreadcrumbs: true, + hideInPageTOC: true, + useCodeBlocks: true, + typeDeclarationFormat: 'table', + propertiesFormat: 'table', + parametersFormat: 'table', + enumMembersFormat: 'table', + indexFormat: 'table', + outputFileStrategy: 'members', + memberPageTitle: '{name}', + membersWithOwnFile: ['Interface', 'Class', 'TypeAlias', 'Function'], + }, + ], + [ + 'docusaurus-plugin-typedoc', + { + id: 'noir_wasm', + entryPoints: ['../compiler/wasm/src/index.cts'], + tsconfig: '../compiler/wasm/tsconfig.json', + entryPointStrategy: 'resolve', + out: 'processed-docs/reference/NoirJS/noir_wasm', + plugin: ['typedoc-plugin-markdown'], + name: 'noir_wasm', + disableSources: true, + excludePrivate: true, + skipErrorChecking: true, + sidebar: { + filteredIds: ['reference/noir_wasm/index'], + }, + readme: 'none', + hidePageHeader: true, + hideBreadcrumbs: true, + hideInPageTOC: true, + useCodeBlocks: true, + typeDeclarationFormat: 'table', + propertiesFormat: 'table', + parametersFormat: 'table', + enumMembersFormat: 'table', + indexFormat: 'table', + outputFileStrategy: 'members', + memberPageTitle: '{name}', + membersWithOwnFile: ['Function', 'TypeAlias'], + }, + ], + ], + markdown: { + format: 'detect', + }, +} satisfies Config; diff --git a/docs/link-check.config.json b/docs/link-check.config.json new file mode 100644 index 00000000000..68059476958 --- /dev/null +++ b/docs/link-check.config.json @@ -0,0 +1,7 @@ +{ + "ignorePatterns": [ + { + "pattern": "^[^\/]+\/[^\/].*$|^\/[^\/].*$" + } + ] +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 00000000000..39807588eaa --- /dev/null +++ b/docs/package.json @@ -0,0 +1,64 @@ +{ + "name": "docs", + "version": "0.0.0", + "private": true, + "scripts": { + "preprocess": "yarn workspace @noir-lang/acvm_js build && ./scripts/codegen_nargo_reference.sh && yarn node ./scripts/preprocess/index.js", + "dev": "yarn preprocess && 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", + "swizzle": "docusaurus swizzle", + "version": "yarn version::stables && ./scripts/cut_version.sh" + }, + "dependencies": { + "@docusaurus/core": "^3.5.2", + "@docusaurus/preset-classic": "^3.5.2", + "@easyops-cn/docusaurus-search-local": "^0.35.0", + "@mdx-js/react": "^3.0.0", + "@noir-lang/noir_js": "workspace:*", + "@noir-lang/noirc_abi": "workspace:*", + "@noir-lang/types": "workspace:*", + "axios": "^1.4.0", + "clsx": "^1.2.1", + "hast-util-is-element": "^1.1.0", + "prism-react-renderer": "^2.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-spinners": "^0.13.8", + "rehype-katex": "^7.0.0", + "remark-math": "^6.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "^3.5.2", + "@docusaurus/tsconfig": "^3.5.2", + "@docusaurus/types": "^3.5.2", + "@types/prettier": "^3", + "docusaurus-plugin-typedoc": "1.0.0-next.18", + "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.4.2" + }, + "browserslist": { + "production": [ + ">0.5%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "engines": { + "node": ">=18-0" + } +} diff --git a/docs/scripts/codegen_nargo_reference.sh b/docs/scripts/codegen_nargo_reference.sh new file mode 100755 index 00000000000..6a9fda9420b --- /dev/null +++ b/docs/scripts/codegen_nargo_reference.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -eu + +cd $(dirname "$0")/.. + +REFERENCE_DIR="./processed-docs/reference" +NARGO_REFERENCE="$REFERENCE_DIR/nargo_commands.md" +rm -f $NARGO_REFERENCE +mkdir -p $REFERENCE_DIR + +echo "--- +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 +--- +" > $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/scripts/preprocess/include_code.js b/docs/scripts/preprocess/include_code.js new file mode 100644 index 00000000000..ffe50065002 --- /dev/null +++ b/docs/scripts/preprocess/include_code.js @@ -0,0 +1,312 @@ +const fs = require('fs'); +const path = require('path'); +const childProcess = require('child_process'); + +const getLineNumberFromIndex = (fileContent, index) => { + return fileContent.substring(0, index).split('\n').length; +}; + +/** + * Search for lines of the form + */ +function processHighlighting(codeSnippet, identifier) { + const lines = codeSnippet.split('\n'); + /** + * For an identifier = bar: + * + * Matches of the form: `highlight-next-line:foo:bar:baz` will be replaced with "highlight-next-line". + * Matches of the form: `highlight-next-line:foo:baz` will be replaced with "". + */ + const regex1 = /highlight-next-line:([a-zA-Z0-9-._:]+)/; + const replacement1 = 'highlight-next-line'; + const regex2 = /highlight-start:([a-zA-Z0-9-._:]+)/; + const replacement2 = 'highlight-start'; + const regex3 = /highlight-end:([a-zA-Z0-9-._:]+)/; + const replacement3 = 'highlight-end'; + const regex4 = /this-will-error:([a-zA-Z0-9-._:]+)/; + const replacement4 = 'this-will-error'; + + let result = ''; + let mutated = false; + + const processLine = (line, regex, replacement) => { + const match = line.match(regex); + if (match) { + mutated = true; + + const identifiers = match[1].split(':'); + if (identifiers.includes(identifier)) { + line = line.replace(match[0], replacement); + } else { + // Remove matched text completely + line = line.replace(match[0], ''); + } + } else { + // No match: it's an ordinary line of code. + } + return line.trim() == '//' || line.trim() == '#' ? '' : line; + }; + + for (let line of lines) { + mutated = false; + line = processLine(line, regex1, replacement1); + line = processLine(line, regex2, replacement2); + line = processLine(line, regex3, replacement3); + line = processLine(line, regex4, replacement4); + result += line === '' && mutated ? '' : line + '\n'; + } + + return result.trim(); +} + +let lastReleasedVersion; + +/** Returns the last released tag */ +function getLatestTag() { + if (!lastReleasedVersion) { + const manifest = path.resolve(__dirname, '../../../.release-please-manifest.json'); + lastReleasedVersion = JSON.parse(fs.readFileSync(manifest).toString())['.']; + } + return lastReleasedVersion ? `v${lastReleasedVersion}` : undefined; +} + +/** Returns whether to use the latest release or the current version of stuff. */ +function useLastRelease() { + return process.env.NETLIFY || process.env.INCLUDE_RELEASED_CODE; +} + +/** + * Returns the contents of a file. If the build is running for publishing, it will load the contents + * of the file in the last released version. + */ +function readFile(filePath, tag) { + if (tag && tag !== 'master') { + try { + const root = path.resolve(__dirname, '../../../'); + const relPath = path.relative(root, filePath); + const taggedPath = `${tag}:${relPath}`; + return childProcess.execSync('git show', taggedPath).toString(); + } catch (err) { + console.error(`Error reading file ${filePath} from version ${tag}. Falling back to current content.`); + } + } + return fs.readFileSync(filePath, 'utf-8'); +} + +/** Extracts a code snippet, trying with the last release if applicable, and falling back to current content. */ +function extractCodeSnippet(filePath, identifier, requesterFile) { + if (useLastRelease()) { + try { + return doExtractCodeSnippet(filePath, identifier, false); + } catch (err) { + console.error( + `Error extracting code snippet ${identifier} from ${path.basename( + filePath, + )} requested by ${requesterFile}: ${err}. Falling back to current content.`, + ); + } + } + + return doExtractCodeSnippet(filePath, identifier, true); +} + +/** + * Parse a code file, looking for identifiers of the form: + * `docs:start:${identifier}` and `docs:end:{identifier}`. + * Extract that section of code. + * + * It's complicated if code snippet identifiers overlap (i.e. the 'start' of one code snippet is in the + * middle of another code snippet). The extra logic in this function searches for all identifiers, and + * removes any which fall within the bounds of the code snippet for this particular `identifier` param. + * @returns the code snippet, and start and end line numbers which can later be used for creating a link to github source code. + */ +function doExtractCodeSnippet(filePath, identifier, useCurrent) { + const tag = useCurrent ? 'master' : getLatestTag(); + let fileContent = readFile(filePath, tag); + let lineRemovalCount = 0; + let linesToRemove = []; + + const startRegex = /(?:\/\/|#)\s+docs:start:([a-zA-Z0-9-._:]+)/g; // `g` will iterate through the regex.exec loop + const endRegex = /(?:\/\/|#)\s+docs:end:([a-zA-Z0-9-._:]+)/g; + + /** + * Search for one of the regex statements in the code file. If it's found, return the line as a string and the line number. + */ + const lookForMatch = (regex) => { + let match; + let matchFound = false; + let matchedLineNum = null; + let actualMatch = null; + let lines = fileContent.split('\n'); + while ((match = regex.exec(fileContent))) { + if (match !== null) { + const identifiers = match[1].split(':'); + let tempMatch = identifiers.includes(identifier) ? match : null; + + if (tempMatch === null) { + // If it's not a match, we'll make a note that we should remove the matched text, because it's from some other identifier and should not appear in the snippet for this identifier. + for (let i = 0; i < lines.length; i++) { + let line = lines[i]; + if (line.trim() == match[0].trim()) { + linesToRemove.push(i + 1); // lines are indexed from 1 + ++lineRemovalCount; + } + } + } else { + if (matchFound === true) { + throw new Error(`Duplicate for regex ${regex} and identifier ${identifier}`); + } + matchFound = true; + matchedLineNum = getLineNumberFromIndex(fileContent, tempMatch.index); + actualMatch = tempMatch; + } + } + } + + return [actualMatch, matchedLineNum]; + }; + + let [startMatch, startLineNum] = lookForMatch(startRegex); + let [endMatch, endLineNum] = lookForMatch(endRegex); + + // Double-check that the extracted line actually contains the required start and end identifier. + if (startMatch !== null) { + const startIdentifiers = startMatch[1].split(':'); + startMatch = startIdentifiers.includes(identifier) ? startMatch : null; + } + if (endMatch !== null) { + const endIdentifiers = endMatch[1].split(':'); + endMatch = endIdentifiers.includes(identifier) ? endMatch : null; + } + + if (startMatch === null || endMatch === null) { + if (startMatch === null && endMatch === null) { + throw new Error(`Identifier "${identifier}" not found in file "${filePath}"`); + } else if (startMatch === null) { + throw new Error(`Start line "docs:start:${identifier}" not found in file "${filePath}"`); + } else { + throw new Error(`End line "docs:end:${identifier}" not found in file "${filePath}"`); + } + } + + let lines = fileContent.split('\n'); + + // We only want to remove lines which actually fall within the bounds of our code snippet, so narrow down the list of lines that we actually want to remove. + linesToRemove = linesToRemove.filter((lineNum) => { + const removal_in_bounds = lineNum >= startLineNum && lineNum <= endLineNum; + return removal_in_bounds; + }); + + // Remove lines which contain `docs:` comments for unrelated identifiers: + lines = lines.filter((l, i) => { + return !linesToRemove.includes(i + 1); // lines are indexed from 1 + }); + + // Remove lines from the snippet which fall outside the `docs:start` and `docs:end` values. + lines = lines.filter((l, i) => { + return i + 1 > startLineNum && i + 1 < endLineNum - linesToRemove.length; // lines are indexed from 1 + }); + + // We have our code snippet! + let codeSnippet = lines.join('\n'); + + // The code snippet might contain some docusaurus highlighting comments for other identifiers. We should remove those. + codeSnippet = processHighlighting(codeSnippet, identifier); + + return [codeSnippet, startLineNum, endLineNum, tag]; +} + +/** + * Explaining this regex: + * + * E.g. `#include_code snippet_identifier /circuits/my_code.cpp cpp` + * + * #include_code\s+(\S+)\s+(\S+)\s+(\S+) + * - This is the main regex to match the above format. + * - \s+: one or more whitespace characters (space or tab) after `include_code` command. + * - (\S+): one or more non-whitespaced characters. Captures this as the first argument, which is a human-readable identifier for the code block. + * - etc. + * + * Lookaheads are needed to allow us to ignore commented-out lines: + * + * ^(?! feet` binding in the example above. + +### Visibility + +By default, like functions, structs are private to the module they exist in. You can use `pub` +to make the struct public or `pub(crate)` to make it public to just its crate: + +```rust +// This struct is now public +pub struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +The same applies to struct fields: by default they are private to the module they exist in, +but they can be made `pub` or `pub(crate)`: + +```rust +// This struct is now public +pub struct Animal { + hands: Field, // private to its module + pub(crate) legs: Field, // accessible from the entire crate + pub eyes: u8, // accessible from anywhere +} +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.36.0/noir/concepts/data_types/tuples.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/concepts/functions.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/functions.md new file mode 100644 index 00000000000..f656cdfd97a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/concepts/generics.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/generics.md new file mode 100644 index 00000000000..c180a0ce7e6 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/concepts/generics.md @@ -0,0 +1,251 @@ +--- +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 +} +``` + +## Numeric Generics + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks similar to using regular generics, but introducing them into scope +requires declaring them with `let MyGenericName: IntegerType`. This can be done anywhere a normal +generic is declared. Instead of types, these generics resolve to integers at compile-time. +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 + } +} +``` + +## 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. + +## 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.md) 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.md). + +## Manually Specifying Generics with the Turbofish Operator + +There are times when the compiler cannot reasonably infer what type should be used for a generic, or when the developer themselves may want to manually distinguish generic type parameters. This is where the `::<>` turbofish operator comes into play. + +The `::<>` operator can follow a variable or path and can be used to manually specify generic arguments within the angle brackets. +The name "turbofish" comes from that `::<>` looks like a little fish. + +Examples: +```rust +fn main() { + let mut slice = []; + slice = slice.push_back(1); + slice = slice.push_back(2); + // Without turbofish a type annotation would be needed on the left hand side + let array = slice.as_array::<2>(); +} +``` + + +```rust +trait MyTrait { + fn ten() -> Self; +} + +impl MyTrait for Field { + fn ten() -> Self { 10 } +} + +struct Foo { + inner: T +} + +impl Foo { + fn generic_method(_self: Self) -> U where U: MyTrait { + U::ten() + } +} + +fn example() { + let foo: Foo = Foo { inner: 1 }; + // Using a type other than `Field` here (e.g. u32) would fail as + // there is no matching impl for `u32: MyTrait`. + // + // Substituting the `10` on the left hand side of this assert + // with `10 as u32` would also fail with a type mismatch as we + // are expecting a `Field` from the right hand side. + assert(10 as u32 == foo.generic_method::()); +} +``` + +## Arithmetic Generics + +In addition to numeric generics, Noir also allows a limited form of arithmetic on generics. +When you have a numeric generic such as `N`, you can use the following operators on it in a +type position: `+`, `-`, `*`, `/`, and `%`. + +Note that type checking arithmetic generics is a best effort guess from the compiler and there +are many cases of types that are equal that the compiler may not see as such. For example, +we know that `T * (N + M)` should be equal to `T*N + T*M` but the compiler does not currently +apply the distributive law and thus sees these as different types. + +Even with this limitation though, the compiler can handle common cases decently well: + +```rust +trait Serialize { + fn serialize(self) -> [Field; N]; +} + +impl Serialize<1> for Field { + fn serialize(self) -> [Field; 1] { + [self] + } +} + +impl Serialize for [T; N] + where T: Serialize { .. } + +impl Serialize for (T, U) + where T: Serialize, U: Serialize { .. } + +fn main() { + let data = (1, [2, 3, 4]); + assert_eq(data.serialize().len(), 4); +} +``` + +Note that if there is any over or underflow the types will fail to unify: + +```rust title="underflow-example" showLineNumbers +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn main() { + // error: Could not determine array length `(0 - 1)` + pop([]); +} +``` +>
Source code: test_programs/compile_failure/arithmetic_generics_underflow/src/main.nr#L1-L14 + + +This also applies if there is underflow in an intermediate calculation: + +```rust title="intermediate-underflow-example" showLineNumbers +fn main() { + // From main it looks like there's nothing sketchy going on + seems_fine([]); +} + +// Since `seems_fine` says it can receive and return any length N +fn seems_fine(array: [Field; N]) -> [Field; N] { + // But inside `seems_fine` we pop from the array which + // requires the length to be greater than zero. + + // error: Could not determine array length `(0 - 1)` + push_zero(pop(array)) +} + +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn push_zero(array: [Field; N]) -> [Field; N + 1] { + let mut result: [Field; N + 1] = std::mem::zeroed(); + for i in 0..N { + result[i] = array[i]; + } + // index N is already zeroed + result +} +``` +> Source code: test_programs/compile_failure/arithmetic_generics_intermediate_underflow/src/main.nr#L1-L32 + diff --git a/docs/versioned_docs/version-v0.36.0/noir/concepts/globals.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/globals.md new file mode 100644 index 00000000000..6b8314399a2 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/concepts/globals.md @@ -0,0 +1,82 @@ +--- +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: u32 = 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. + +### Visibility + +By default, like functions, globals are private to the module they exist in. You can use `pub` +to make the global public or `pub(crate)` to make it public to just its crate: + +```rust +// This global is now public +pub global N = 5; +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.36.0/noir/concepts/lambdas.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/concepts/mutability.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/concepts/ops.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/ops.md new file mode 100644 index 00000000000..c35c36c38a9 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/concepts/oracles.mdx b/docs/versioned_docs/version-v0.36.0/noir/concepts/oracles.mdx new file mode 100644 index 00000000000..77a2ac1550a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/concepts/oracles.mdx @@ -0,0 +1,29 @@ +--- +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 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +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.36.0/noir/concepts/shadowing.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/concepts/traits.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/traits.md new file mode 100644 index 00000000000..9da00a77587 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/concepts/traits.md @@ -0,0 +1,501 @@ +--- +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 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; let N: u32] 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 + } +} +``` + +Where clauses can also be placed on struct implementations. +For example, here is a method utilizing a generic type that implements the equality trait. + +```rust +struct Foo { + a: u32, + b: T, +} + +impl Foo where T: Eq { + fn eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.eq(other.b) + } +} +``` + +## 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); +} +``` + +### Associated Types and Constants + +Traits also support associated types and constraints which can be thought of as additional generics that are referred to by name. + +Here's an example of a trait with an associated type `Foo` and a constant `Bar`: + +```rust +trait MyTrait { + type Foo; + + let Bar: u32; +} +``` + +Now when we're implementing `MyTrait` we also have to provide values for `Foo` and `Bar`: + +```rust +impl MyTrait for Field { + type Foo = i32; + + let Bar: u32 = 11; +} +``` + +Since associated constants can also be used in a type position, its values are limited to only other +expression kinds allowed in numeric generics. + +Note that currently all associated types and constants must be explicitly specified in a trait constraint. +If we leave out any, we'll get an error that we're missing one: + +```rust +// Error! Constraint is missing associated constant for `Bar` +fn foo(x: T) where T: MyTrait { + ... +} +``` + +Because all associated types and constants must be explicitly specified, they are essentially named generics, +although this is set to change in the future. Future versions of Noir will allow users to elide associated types +in trait constraints similar to Rust. When this is done, you may still refer to their value with the `::AssociatedType` +syntax: + +```rust +// Only valid in future versions of Noir: +fn foo(x: T) where T: MyTrait { + let _: ::Foo = ...; +} +``` + +The type as trait syntax is possible in Noir today but is less useful when each type must be explicitly specified anyway: + +```rust +fn foo(x: T) where T: MyTrait { + // Works, but could just use F directly + let _: >::Foo = ...; + + let _: F = ...; +} +``` + +## 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: some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: 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. + +### Trait Inheritance + +Sometimes, you might need one trait to use another trait’s functionality (like "inheritance" in some other languages). In this case, you can specify this relationship by listing any child traits after the parent trait's name and a colon. Now, whenever the parent trait is implemented it will require the child traits to be implemented as well. A parent trait is also called a "super trait." + +```rust +trait Person { + fn name(self) -> String; +} + +// Person is a supertrait of Student. +// Implementing Student requires you to also impl Person. +trait Student: Person { + fn university(self) -> String; +} + +trait Programmer { + fn fav_language(self) -> String; +} + +// CompSciStudent (computer science student) is a subtrait of both Programmer +// and Student. Implementing CompSciStudent requires you to impl both supertraits. +trait CompSciStudent: Programmer + Student { + fn git_username(self) -> String; +} +``` + +### Visibility + +By default, like functions, traits are private to the module they exist in. You can use `pub` +to make the trait public or `pub(crate)` to make it public to just its crate: + +```rust +// This trait is now public +pub trait Trait {} +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.36.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v0.36.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..b5221b8d2dd --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/concepts/unconstrained.md @@ -0,0 +1,104 @@ +--- +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 = unsafe { + 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). + +Note that in order to invoke unconstrained functions we need to wrap them in an `unsafe` block, +to make it clear that the call is unconstrained. + +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.md#break-and-continue) diff --git a/docs/versioned_docs/version-v0.36.0/noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v0.36.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.36.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.36.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..24e02de08fe --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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 ecrecover; +use lib_a; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use std::hash::sha256; +use std::scalar_mul::fixed_base_embedded_curve; +``` + +Lastly, as demonstrated in the +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you +can import multiple items in the same line by enclosing them in curly braces: + +```rust +use std::ec::tecurve::affine::{Curve, Point}; +``` + +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) 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 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.36.0/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.36.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..14aa1f0579a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,221 @@ +--- +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 + +``` + +The module filename may also be the name of the module as a directory with the contents in a +file named `mod.nr` within that directory. The above example can alternatively be expressed like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +fn from_foo() {} +``` + +Note that it's an error to have both files `src/foo.nr` and `src/foo/mod.nr` in the filesystem. + +### 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 +``` + +Similar to importing a module in the crate root, modules can be placed in a `mod.nr` file, like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar/mod.nr` + +```rust +fn from_bar() {} +``` + +### Referencing a parent module + +Given a submodule, you can refer to its parent module using the `super` keyword. + +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 +// Same as bar::from_foo +use super::from_foo; + +fn from_bar() { + from_foo(); // invokes super::from_foo(), which is bar::from_foo() + super::from_foo(); // also invokes bar::from_foo() +} +``` + +### `use` visibility + +`use` declarations are private to the containing module, by default. However, like functions, +they can be marked as `pub` or `pub(crate)`. Such a use declaration serves to _re-export_ a name. +A public `use` declaration can therefore redirect some public name to a different target definition: +even a definition with a private canonical path, inside a different module. + +An example of re-exporting: + +```rust +mod some_module { + pub use foo::{bar, baz}; + mod foo { + pub fn bar() {} + pub fn baz() {} + } +} + +fn main() { + some_module::bar(); + some_module::baz(); +} +``` + +In this example, the module `some_module` re-exports two public names defined in `foo`. + +### Visibility + +By default, like functions, modules are private to the module (or crate) they exist in. You can use `pub` +to make the module public or `pub(crate)` to make it public to just its crate: + +```rust +// This module is now public and can be seen by other crates. +pub mod foo; +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.36.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.36.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..513497f12bf --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/standard_library/_category_.json b/docs/versioned_docs/version-v0.36.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..e275f03bc6a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/standard_library/bigint.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/bigint.md new file mode 100644 index 00000000000..05c3011634f --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/bigint.md @@ -0,0 +1,127 @@ +--- +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. + +:::note + +`nargo` can be built with `--profile release-pedantic` to enable extra overflow checks which may affect `BigInt` results in some cases. +Consider the [`noir-bignum`](https://github.com/noir-lang/noir-bignum) library for an optimized alternative approach. + +::: + +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 +pub struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L28-L33 + + +## 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#L74-L82 + + +## 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.36.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..d6079ab182c --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.mdx) + +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.36.0/noir/standard_library/bn254.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/standard_library/containers/boundedvec.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..509b214bf3a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,419 @@ +--- +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 good() -> 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 `good`'s return value + v2 +} + +fn bad() { + // Error: Type annotation needed + // The compiler can't infer `MaxLen` from this code. + let mut v3 = BoundedVec::new(); + 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(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(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 + + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to 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); + assert(first != 42); + v.set(0, 42); + let new_first = v.get(0); + assert(new_first == 42); +} +``` + +### set_unchecked + +```rust +pub fn set_unchecked(&mut self: Self, index: u64, value: T) -> T { +``` + +Writes an element to 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="set_unchecked_example" showLineNumbers +fn set_unchecked_example() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2]); + + // Here we're safely writing within the valid range of `vec` + // `vec` now has the value [42, 2] + vec.set_unchecked(0, 42); + + // We can then safely read this value back out of `vec`. + // Notice that we use the checked version of `get` which would prevent reading unsafe values. + assert_eq(vec.get(0), 42); + + // We've now written past the end of `vec`. + // As this index is still within the maximum potential length of `v`, + // it won't cause a constraint failure. + vec.set_unchecked(2, 42); + println(vec); + + // This will write past the end of the maximum potential length of `vec`, + // it will then trigger a constraint failure. + vec.set_unchecked(5, 42); + println(vec); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L67-L91 + + + +### 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#L95-L103 + + +### 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#L108-L120 + + +### 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#L125-L140 + + +### 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#L145-L151 + + +### 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#L156-L163 + + +### 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#L168-L175 + + +### 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#L180-L189 + + +### 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]) +``` + +### map + +```rust +pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec +``` + +Creates a new vector of equal size by calling a closure on each element in this vector. + +Example: + +```rust title="bounded-vec-map-example" showLineNumbers +let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| value * 2); +``` +> Source code: noir_stdlib/src/collections/bounded_vec.nr#L495-L498 + + +### 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#L256-L262 + diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/containers/hashmap.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..395cc312705 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,587 @@ +--- +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`. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a poseidon2 hasher +use 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, +{ + /// Constructs an empty HashMap. + /// + /// Example: + /// + /// ```noir + /// let hashmap: HashMap> = HashMap::default(); + /// assert(hashmap.is_empty()); + /// ``` + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L681-L696 + + +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#L207-L210 + + +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#L201-L203 + + +### 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#L103-L108 + + +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#L211-L216 + + +### 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#L465-L472 + + +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#L296-L304 + + +### 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#L507-L514 + + +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#L217-L221 + + +### 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#L563-L570 + + +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#L224-L231 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L167-L169 + + +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#L232-L240 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L424-L426 + + +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#L241-L256 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L446-L448 + + +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-L262 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +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#L143-L150 + + +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#L268-L275 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L191-L193 + + +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#L307-L318 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L227-L229 + + +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#L319-L329 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L262-L264 + + +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#L330-L339 + + +### 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#L297-L304 + + +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#L343-L346 + + +### 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#L335-L342 + + +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#L347-L350 + + +### 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#L367-L369 + + +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#L351-L354 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L388-L390 + + +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#L279-L281 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default, +{ + /// Constructs an empty HashMap. + /// + /// Example: + /// + /// ```noir + /// let hashmap: HashMap> = HashMap::default(); + /// assert(hashmap.is_empty()); + /// ``` + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L681-L696 + + +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#L207-L210 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher, +{ + /// Checks if two HashMaps are equal. + /// + /// Example: + /// + /// ```noir + /// 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); + /// ``` + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L629-L654 + + +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#L282-L293 + diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/containers/index.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/standard_library/containers/vec.mdx b/docs/versioned_docs/version-v0.36.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..475011922f8 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,170 @@ +--- +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); +``` + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +Panics if the index points beyond the vector's end. + +Example: + +```rust +let vector: Vec = Vec::from_slice(&[10, 20, 30]); +assert(vector.get(1) == 20); +vector.set(1, 42); +assert(vector.get(1) == 42); +``` + +### 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.36.0/noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/standard_library/cryptographic_primitives/ciphers.mdx b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/ciphers.mdx new file mode 100644 index 00000000000..d6a5e1a79eb --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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'; + +## 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.36.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..f262d8160d6 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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/mod.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec/mod.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/mod.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 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.36.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..8d96027b42c --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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'; + +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.36.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..b283de693c8 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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'; + +## 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` 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 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/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx new file mode 100644 index 00000000000..4b5bba7802e --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx @@ -0,0 +1,95 @@ +--- +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'; + +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: [EmbeddedCurvePoint; N], + scalars: [EmbeddedCurveScalar; N], +) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L103-L108 + + +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: EmbeddedCurveScalar) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L126-L128 + + +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 +pub fn embedded_curve_add( + point1: EmbeddedCurvePoint, + point2: EmbeddedCurvePoint, +) -> EmbeddedCurvePoint { +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L142-L147 + + +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.36.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..7cb95779586 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,253 @@ +--- +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'; + +## 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/sha256.nr#L7-L9 + + +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#L15-L17 + + +```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/mod.nr#L20-L22 + + +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/mod.nr#L26-L28 + + +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/mod.nr#L51-L53 + + +example: + +```rust title="pedersen-hash" showLineNumbers +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-L6 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { +``` +> Source code: noir_stdlib/src/hash/mod.nr#L31-L33 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +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); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L7 + + + + +## 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/mod.nr#L117-L119 + + +example: + +```rust title="keccak256" showLineNumbers +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-L20 + + + + +## 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 std::hash::poseidon; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L11 + + +## 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); +``` + +example: + +```rust title="poseidon2" showLineNumbers +use std::hash::poseidon2; + +fn main(inputs: [Field; 4], expected_hash: Field) { + let hash = poseidon2::Poseidon2::hash(inputs, inputs.len()); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/poseidon2/src/main.nr#L1-L8 + + +## 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.36.0/noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v0.36.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..030452645c5 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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'; + +## 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#L4-L11 + + +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#L15-L22 + + + diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/fmtstr.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/fmtstr.md new file mode 100644 index 00000000000..19809d60261 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/fmtstr.md @@ -0,0 +1,17 @@ +--- +title: fmtstr +--- + +`fmtstr` is the type resulting from using format string (`f"..."`). + +## Methods + +### quoted_contents + +```rust title="quoted_contents" showLineNumbers +pub comptime fn quoted_contents(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/format_string.nr#L3-L5 + + +Returns the format string contents (that is, without the leading and trailing double quotes) as a `Quoted` value. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/is_unconstrained.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/is_unconstrained.md new file mode 100644 index 00000000000..51bb1bda8f1 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/is_unconstrained.md @@ -0,0 +1,69 @@ +--- +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. + +Note that using `is_unconstrained` in a `comptime` context will also return `true`: + +``` +fn main() { + comptime { + assert(is_unconstrained()); + } +} +``` diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/logging.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/standard_library/mem.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/mem.md new file mode 100644 index 00000000000..95d36ac2a72 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/mem.md @@ -0,0 +1,52 @@ +--- +title: Memory Module +description: + This module contains functions which manipulate memory in a low-level way +keywords: + [ + mem, memory, zeroed, transmute, checked_transmute + ] +--- + +# `std::mem::zeroed` + +```rust +fn zeroed() -> T +``` + +Returns 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. + +This function currently supports the following types: + +- Field +- Bool +- Uint +- Array +- Slice +- String +- Tuple +- Functions + +Using it on other types could result in unexpected behavior. + +# `std::mem::checked_transmute` + +```rust +fn checked_transmute(value: T) -> U +``` + +Transmutes a value of one type into the same value but with a new type `U`. + +This function is safe to use since both types are asserted to be equal later during compilation after the concrete values for generic types become known. +This function is useful for cases where the compiler may fails a type check that is expected to pass where +a user knows the two types to be equal. For example, when using arithmetic generics there are cases the compiler +does not see as equal, such as `[Field; N*(A + B)]` and `[Field; N*A + N*B]`, which users may know to be equal. +In these cases, `checked_transmute` can be used to cast the value to the desired type while also preserving safety +by checking this equality once `N`, `A`, `B` are fully resolved. + +Note that since this safety check is performed after type checking rather than during, no error is issued if the function +containing `checked_transmute` is never called. diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..6a9ebf72ada --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/standard_library/meta/ctstring.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/ctstring.md new file mode 100644 index 00000000000..b76f873ca03 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/ctstring.md @@ -0,0 +1,100 @@ +--- +title: CtString +--- + +`std::meta::ctstring` contains methods on the built-in `CtString` type which is +a compile-time, dynamically-sized string type. Compared to `str` and `fmtstr`, +`CtString` is useful because its size does not need to be specified in its type. This +can be used for formatting items at compile-time or general string handling in `comptime` +code. + +Since `fmtstr`s can be converted into `CtString`s, you can make use of their formatting +abilities in CtStrings by formatting in `fmtstr`s then converting the result to a CtString +afterward. + +## Traits + +### AsCtString + +```rust title="as-ctstring" showLineNumbers +pub trait AsCtString { + comptime fn as_ctstring(self) -> CtString; +} +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L43-L47 + + +Converts an object into a compile-time string. + +Implementations: + +```rust +impl AsCtString for str { ... } +impl AsCtString for fmtstr { ... } +``` + +## Methods + +### new + +```rust title="new" showLineNumbers +pub comptime fn new() -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L4-L6 + + +Creates an empty `CtString`. + +### append_str + +```rust title="append_str" showLineNumbers +pub comptime fn append_str(self, s: str) -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L11-L13 + + +Returns a new CtString with the given str appended onto the end. + +### append_fmtstr + +```rust title="append_fmtstr" showLineNumbers +pub comptime fn append_fmtstr(self, s: fmtstr) -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L17-L19 + + +Returns a new CtString with the given fmtstr appended onto the end. + +### as_quoted_str + +```rust title="as_quoted_str" showLineNumbers +pub comptime fn as_quoted_str(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L26-L28 + + +Returns a quoted string literal from this string's contents. + +There is no direct conversion from a `CtString` to a `str` since +the size would not be known. To get around this, this function can +be used in combination with macro insertion (`!`) to insert this string +literal at this function's call site. + +Example: + +```rust title="as_quoted_str_example" showLineNumbers +let my_ctstring = "foo bar".as_ctstring(); + let my_str = my_ctstring.as_quoted_str!(); + + assert_eq(crate::meta::type_of(my_str), quote { str<7> }.as_type()); +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L92-L97 + + +## Trait Implementations + +```rust +impl Eq for CtString +impl Hash for CtString +impl Append for CtString +``` diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/expr.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/expr.md new file mode 100644 index 00000000000..b6d395c6700 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/expr.md @@ -0,0 +1,380 @@ +--- +title: Expr +--- + +`std::meta::expr` contains methods on the built-in `Expr` type for quoted, syntactically valid expressions. + +## Methods + +### as_array + +```rust title="as_array" showLineNumbers +pub comptime fn as_array(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L10-L12 + + +If this expression is an array, this returns a slice of each element in the array. + +### as_assert + +```rust title="as_assert" showLineNumbers +pub comptime fn as_assert(self) -> Option<(Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L16-L18 + + +If this expression is an assert, this returns the assert expression and the optional message. + +### as_assert_eq + +```rust title="as_assert_eq" showLineNumbers +pub comptime fn as_assert_eq(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L23-L25 + + +If this expression is an assert_eq, this returns the left-hand-side and right-hand-side +expressions, together with the optional message. + +### as_assign + +```rust title="as_assign" showLineNumbers +pub comptime fn as_assign(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L30-L32 + + +If this expression is an assignment, this returns a tuple with the left hand side +and right hand side in order. + +### as_binary_op + +```rust title="as_binary_op" showLineNumbers +pub comptime fn as_binary_op(self) -> Option<(Expr, BinaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L37-L39 + + +If this expression is a binary operator operation ` `, +return the left-hand side, operator, and the right-hand side of the operation. + +### as_block + +```rust title="as_block" showLineNumbers +pub comptime fn as_block(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L44-L46 + + +If this expression is a block `{ stmt1; stmt2; ...; stmtN }`, return +a slice containing each statement. + +### as_bool + +```rust title="as_bool" showLineNumbers +pub comptime fn as_bool(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L50-L52 + + +If this expression is a boolean literal, return that literal. + +### as_cast + +```rust title="as_cast" showLineNumbers +#[builtin(expr_as_cast)] + pub comptime fn as_cast(self) -> Option<(Expr, UnresolvedType)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L56-L59 + + +If this expression is a cast expression (`expr as type`), returns the casted +expression and the type to cast to. + +### as_comptime + +```rust title="as_comptime" showLineNumbers +pub comptime fn as_comptime(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L64-L66 + + +If this expression is a `comptime { stmt1; stmt2; ...; stmtN }` block, +return each statement in the block. + +### as_constructor + +```rust title="as_constructor" showLineNumbers +pub comptime fn as_constructor(self) -> Option<(UnresolvedType, [(Quoted, Expr)])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L71-L73 + + +If this expression is a constructor `Type { field1: expr1, ..., fieldN: exprN }`, +return the type and the fields. + +### as_for + +```rust title="as_for" showLineNumbers +pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L78-L80 + + +If this expression is a for statement over a single expression, return the identifier, +the expression and the for loop body. + +### as_for_range + +```rust title="as_for" showLineNumbers +pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L78-L80 + + +If this expression is a for statement over a range, return the identifier, +the range start, the range end and the for loop body. + +### as_function_call + +```rust title="as_function_call" showLineNumbers +pub comptime fn as_function_call(self) -> Option<(Expr, [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L92-L94 + + +If this expression is a function call `foo(arg1, ..., argN)`, return +the function and a slice of each argument. + +### as_if + +```rust title="as_if" showLineNumbers +pub comptime fn as_if(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L100-L102 + + +If this expression is an `if condition { then_branch } else { else_branch }`, +return the condition, then branch, and else branch. If there is no else branch, +`None` is returned for that branch instead. + +### as_index + +```rust title="as_index" showLineNumbers +pub comptime fn as_index(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L107-L109 + + +If this expression is an index into an array `array[index]`, return the +array and the index. + +### as_integer + +```rust title="as_integer" showLineNumbers +pub comptime fn as_integer(self) -> Option<(Field, bool)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L114-L116 + + +If this expression is an integer literal, return the integer as a field +as well as whether the integer is negative (true) or not (false). + +### as_lambda + +```rust title="as_lambda" showLineNumbers +pub comptime fn as_lambda( + self, + ) -> Option<([(Expr, Option)], Option, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L120-L124 + + +If this expression is a lambda, returns the parameters, return type and body. + +### as_let + +```rust title="as_let" showLineNumbers +pub comptime fn as_let(self) -> Option<(Expr, Option, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L129-L131 + + +If this expression is a let statement, returns the let pattern as an `Expr`, +the optional type annotation, and the assigned expression. + +### as_member_access + +```rust title="as_member_access" showLineNumbers +pub comptime fn as_member_access(self) -> Option<(Expr, Quoted)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L136-L138 + + +If this expression is a member access `foo.bar`, return the struct/tuple +expression and the field. The field will be represented as a quoted value. + +### as_method_call + +```rust title="as_method_call" showLineNumbers +pub comptime fn as_method_call(self) -> Option<(Expr, Quoted, [UnresolvedType], [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L143-L145 + + +If this expression is a method call `foo.bar::(arg1, ..., argN)`, return +the receiver, method name, a slice of each generic argument, and a slice of each argument. + +### as_repeated_element_array + +```rust title="as_repeated_element_array" showLineNumbers +pub comptime fn as_repeated_element_array(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L150-L152 + + +If this expression is a repeated element array `[elem; length]`, return +the repeated element and the length expressions. + +### as_repeated_element_slice + +```rust title="as_repeated_element_slice" showLineNumbers +pub comptime fn as_repeated_element_slice(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L157-L159 + + +If this expression is a repeated element slice `[elem; length]`, return +the repeated element and the length expressions. + +### as_slice + +```rust title="as_slice" showLineNumbers +pub comptime fn as_slice(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L164-L166 + + +If this expression is a slice literal `&[elem1, ..., elemN]`, +return each element of the slice. + +### as_tuple + +```rust title="as_tuple" showLineNumbers +pub comptime fn as_tuple(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L171-L173 + + +If this expression is a tuple `(field1, ..., fieldN)`, +return each element of the tuple. + +### as_unary_op + +```rust title="as_unary_op" showLineNumbers +pub comptime fn as_unary_op(self) -> Option<(UnaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L178-L180 + + +If this expression is a unary operation ` `, +return the unary operator as well as the right-hand side expression. + +### as_unsafe + +```rust title="as_unsafe" showLineNumbers +pub comptime fn as_unsafe(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L185-L187 + + +If this expression is an `unsafe { stmt1; ...; stmtN }` block, +return each statement inside in a slice. + +### has_semicolon + +```rust title="has_semicolon" showLineNumbers +pub comptime fn has_semicolon(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L206-L208 + + +`true` if this expression is trailed by a semicolon. E.g. + +``` +comptime { + let expr1 = quote { 1 + 2 }.as_expr().unwrap(); + let expr2 = quote { 1 + 2; }.as_expr().unwrap(); + + assert(expr1.as_binary_op().is_some()); + assert(expr2.as_binary_op().is_some()); + + assert(!expr1.has_semicolon()); + assert(expr2.has_semicolon()); +} +``` + +### is_break + +```rust title="is_break" showLineNumbers +pub comptime fn is_break(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L212-L214 + + +`true` if this expression is `break`. + +### is_continue + +```rust title="is_continue" showLineNumbers +pub comptime fn is_continue(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L218-L220 + + +`true` if this expression is `continue`. + +### modify + +```rust title="modify" showLineNumbers +pub comptime fn modify(self, f: fn[Env](Expr) -> Option) -> Expr { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L229-L231 + + +Applies a mapping function to this expression and to all of its sub-expressions. +`f` will be applied to each sub-expression first, then applied to the expression itself. + +This happens recursively for every expression within `self`. + +For example, calling `modify` on `(&[1], &[2, 3])` with an `f` that returns `Option::some` +for expressions that are integers, doubling them, would return `(&[2], &[4, 6])`. + +### quoted + +```rust title="quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L266-L268 + + +Returns this expression as a `Quoted` value. It's the same as `quote { $self }`. + +### resolve + +```rust title="resolve" showLineNumbers +pub comptime fn resolve(self, in_function: Option) -> TypedExpr {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L282-L284 + + +Resolves and type-checks this expression and returns the result as a `TypedExpr`. + +The `in_function` argument specifies where the expression is resolved: +- If it's `none`, the expression is resolved in the function where `resolve` was called +- If it's `some`, the expression is resolved in the given function + +If any names used by this expression are not in scope or if there are any type errors, +this will give compiler errors as if the expression was written directly into +the current `comptime` function. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/function_def.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/function_def.md new file mode 100644 index 00000000000..b7f2ebdb889 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/function_def.md @@ -0,0 +1,166 @@ +--- +title: FunctionDefinition +--- + +`std::meta::function_def` contains methods on the built-in `FunctionDefinition` type representing +a function definition in the source program. + +## Methods + +### add_attribute + +```rust title="add_attribute" showLineNumbers +pub comptime fn add_attribute(self, attribute: str) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L3-L5 + + +Adds an attribute to the function. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### body + +```rust title="body" showLineNumbers +pub comptime fn body(self) -> Expr {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L8-L10 + + +Returns the body of the function as an expression. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +pub comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L13-L15 + + +Returns true if this function has a custom attribute with the given name. + +### is_unconstrained + +```rust title="is_unconstrained" showLineNumbers +pub comptime fn is_unconstrained(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L18-L20 + + +Returns true if this function is unconstrained. + +### module + +```rust title="module" showLineNumbers +pub comptime fn module(self) -> Module {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L23-L25 + + +Returns the module where the function is defined. + +### name + +```rust title="name" showLineNumbers +pub comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L28-L30 + + +Returns the name of the function. + +### parameters + +```rust title="parameters" showLineNumbers +pub comptime fn parameters(self) -> [(Quoted, Type)] {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L33-L35 + + +Returns each parameter of the function as a tuple of (parameter pattern, parameter type). + +### return_type + +```rust title="return_type" showLineNumbers +pub comptime fn return_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L38-L40 + + +The return type of the function. + +### set_body + +```rust title="set_body" showLineNumbers +pub comptime fn set_body(self, body: Expr) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L43-L45 + + +Mutate the function body to a new expression. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_parameters + +```rust title="set_parameters" showLineNumbers +pub comptime fn set_parameters(self, parameters: [(Quoted, Type)]) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L48-L50 + + +Mutates the function's parameters to a new set of parameters. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +Expects a slice of (parameter pattern, parameter type) for each parameter. Requires +each parameter pattern to be a syntactically valid parameter. + +### set_return_type + +```rust title="set_return_type" showLineNumbers +pub comptime fn set_return_type(self, return_type: Type) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L53-L55 + + +Mutates the function's return type to a new type. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_return_public + +```rust title="set_return_public" showLineNumbers +pub comptime fn set_return_public(self, public: bool) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L58-L60 + + +Mutates the function's return visibility to public (if `true` is given) or private (if `false` is given). +This is only valid on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_unconstrained + +```rust title="set_unconstrained" showLineNumbers +pub comptime fn set_unconstrained(self, value: bool) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L66-L68 + + +Mutates the function to be unconstrained (if `true` is given) or not (if `false` is given). +This is only valid on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +## Trait Implementations + +```rust +impl Eq for FunctionDefinition +impl Hash for FunctionDefinition +``` + +Note that each function is assigned a unique ID internally and this is what is used for +equality and hashing. So even functions with identical signatures and bodies may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/index.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/index.md new file mode 100644 index 00000000000..65572d5e815 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/index.md @@ -0,0 +1,224 @@ +--- +title: Metaprogramming +description: Noir's Metaprogramming API +keywords: [metaprogramming, comptime, macros, macro, quote, unquote] +--- + +`std::meta` is the entry point for Noir's metaprogramming API. This consists of `comptime` functions +and types used for inspecting and modifying Noir programs. + +## Functions + +### type_of + +```rust title="type_of" showLineNumbers +pub comptime fn type_of(x: T) -> Type {} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L27-L29 + + +Returns the type of a variable at compile-time. + +Example: +```rust +comptime { + let x: i32 = 1; + let x_type: Type = std::meta::type_of(x); + + assert_eq(x_type, quote { i32 }.as_type()); +} +``` + +### unquote + +```rust title="unquote" showLineNumbers +pub comptime fn unquote(code: Quoted) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L19-L21 + + +Unquotes the passed-in token stream where this function was called. + +Example: +```rust +comptime { + let code = quote { 1 + 2 }; + + // let x = 1 + 2; + let x = unquote!(code); +} +``` + +### derive + +```rust title="derive" showLineNumbers +#[varargs] +pub comptime fn derive(s: StructDefinition, traits: [TraitDefinition]) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L48-L51 + + +Attribute placed on struct definitions. + +Creates a trait impl for each trait passed in as an argument. +To do this, the trait must have a derive handler registered +with `derive_via` beforehand. The traits in the stdlib that +can be derived this way are `Eq`, `Ord`, `Default`, and `Hash`. + +Example: +```rust +#[derive(Eq, Default)] +struct Foo { + x: i32, + y: T, +} + +fn main() { + let foo1 = Foo::default(); + let foo2 = Foo { x: 0, y: &[0] }; + assert_eq(foo1, foo2); +} +``` + +### derive_via + +```rust title="derive_via_signature" showLineNumbers +pub comptime fn derive_via(t: TraitDefinition, f: DeriveFunction) { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L68-L70 + + +Attribute placed on trait definitions. + +Registers a function to create impls for the given trait +when the trait is used in a `derive` call. Users may use +this to register their own functions to enable their traits +to be derived by `derive`. + +Because this function requires a function as an argument which +should produce a trait impl for any given struct, users may find +it helpful to use a function like `std::meta::make_trait_impl` to +help creating these impls. + +Example: +```rust +#[derive_via(derive_do_nothing)] +trait DoNothing { + fn do_nothing(self); +} + +comptime fn derive_do_nothing(s: StructDefinition) -> Quoted { + let typ = s.as_type(); + quote { + impl DoNothing for $typ { + fn do_nothing(self) { + println("Nothing"); + } + } + } +} +``` + +As another example, `derive_eq` in the stdlib is used to derive the `Eq` +trait for any struct. It makes use of `make_trait_impl` to do this: + +```rust title="derive_eq" showLineNumbers +comptime fn derive_eq(s: StructDefinition) -> Quoted { + let signature = quote { fn eq(_self: Self, _other: Self) -> bool }; + let for_each_field = |name| quote { (_self.$name == _other.$name) }; + let body = |fields| { + if s.fields().len() == 0 { + quote { true } + } else { + fields + } + }; + crate::meta::make_trait_impl( + s, + quote { Eq }, + signature, + for_each_field, + quote { & }, + body, + ) +} +``` +> Source code: noir_stdlib/src/cmp.nr#L10-L30 + + +### make_trait_impl + +```rust title="make_trait_impl" showLineNumbers +pub comptime fn make_trait_impl( + s: StructDefinition, + trait_name: Quoted, + function_signature: Quoted, + for_each_field: fn[Env1](Quoted) -> Quoted, + join_fields_with: Quoted, + body: fn[Env2](Quoted) -> Quoted, +) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L87-L96 + + +A helper function to more easily create trait impls while deriving traits. + +Note that this function only works for traits which: +1. Have only one method +2. Have no generics on the trait itself. + - E.g. Using this on a trait such as `trait Foo { ... }` will result in the + generated impl incorrectly missing the `T` generic. + +If your trait fits these criteria then `make_trait_impl` is likely the easiest +way to write your derive handler. The arguments are as follows: + +- `s`: The struct to make the impl for +- `trait_name`: The name of the trait to derive. E.g. `quote { Eq }`. +- `function_signature`: The signature of the trait method to derive. E.g. `fn eq(self, other: Self) -> bool`. +- `for_each_field`: An operation to be performed on each field. E.g. `|name| quote { (self.$name == other.$name) }`. +- `join_fields_with`: A separator to join each result of `for_each_field` with. + E.g. `quote { & }`. You can also use an empty `quote {}` for no separator. +- `body`: The result of the field operations are passed into this function for any final processing. + This is the place to insert any setup/teardown code the trait requires. If the trait doesn't require + any such code, you can return the body as-is: `|body| body`. + +Example deriving `Hash`: + +```rust title="derive_hash" showLineNumbers +comptime fn derive_hash(s: StructDefinition) -> Quoted { + let name = quote { Hash }; + let signature = quote { fn hash(_self: Self, _state: &mut H) where H: std::hash::Hasher }; + let for_each_field = |name| quote { _self.$name.hash(_state); }; + crate::meta::make_trait_impl( + s, + name, + signature, + for_each_field, + quote {}, + |fields| fields, + ) +} +``` +> Source code: noir_stdlib/src/hash/mod.nr#L138-L152 + + +Example deriving `Ord`: + +```rust title="derive_ord" showLineNumbers +comptime fn derive_ord(s: StructDefinition) -> Quoted { + let signature = quote { fn cmp(_self: Self, _other: Self) -> std::cmp::Ordering }; + let for_each_field = |name| quote { + if result == std::cmp::Ordering::equal() { + result = _self.$name.cmp(_other.$name); + } + }; + let body = |fields| quote { + let mut result = std::cmp::Ordering::equal(); + $fields + result + }; + crate::meta::make_trait_impl(s, quote { Ord }, signature, for_each_field, quote {}, body) +} +``` +> Source code: noir_stdlib/src/cmp.nr#L216-L231 + diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/module.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/module.md new file mode 100644 index 00000000000..f47231972b7 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/module.md @@ -0,0 +1,82 @@ +--- +title: Module +--- + +`std::meta::module` contains methods on the built-in `Module` type which represents a module in the source program. +Note that this type represents a module generally, it isn't limited to only `mod my_submodule { ... }` +declarations in the source program. + +## Methods + +### add_item + +```rust title="add_item" showLineNumbers +pub comptime fn add_item(self, item: Quoted) {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L3-L5 + + +Adds a top-level item (a function, a struct, a global, etc.) to the module. +Adding multiple items in one go is also valid if the `Quoted` value has multiple items in it. +Note that the items are type-checked as if they are inside the module they are being added to. + +### functions + +```rust title="functions" showLineNumbers +pub comptime fn functions(self) -> [FunctionDefinition] {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L18-L20 + + +Returns each function defined in the module. + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +pub comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L8-L10 + + +Returns true if this module has a custom attribute with the given name. + +### is_contract + +```rust title="is_contract" showLineNumbers +pub comptime fn is_contract(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L13-L15 + + +`true` if this module is a contract module (was declared via `contract foo { ... }`). + +### name + +```rust title="name" showLineNumbers +pub comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L28-L30 + + +Returns the name of the module. + +### structs + +```rust title="structs" showLineNumbers +pub comptime fn structs(self) -> [StructDefinition] {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L23-L25 + + +Returns each struct defined in the module. + +## Trait Implementations + +```rust +impl Eq for Module +impl Hash for Module +``` + +Note that each module is assigned a unique ID internally and this is what is used for +equality and hashing. So even modules with identical names and contents may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/op.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/op.md new file mode 100644 index 00000000000..03ea49ad8ec --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/op.md @@ -0,0 +1,244 @@ +--- +title: UnaryOp and BinaryOp +--- + +`std::meta::op` contains the `UnaryOp` and `BinaryOp` types as well as methods on them. +These types are used to represent a unary or binary operator respectively in Noir source code. + +## Types + +### UnaryOp + +Represents a unary operator. One of `-`, `!`, `&mut`, or `*`. + +### Methods + +#### is_minus + +```rust title="is_minus" showLineNumbers +pub fn is_minus(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L24-L26 + + +Returns `true` if this operator is `-`. + +#### is_not + +```rust title="is_not" showLineNumbers +pub fn is_not(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L30-L32 + + +`true` if this operator is `!` + +#### is_mutable_reference + +```rust title="is_mutable_reference" showLineNumbers +pub fn is_mutable_reference(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L36-L38 + + +`true` if this operator is `&mut` + +#### is_dereference + +```rust title="is_dereference" showLineNumbers +pub fn is_dereference(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L42-L44 + + +`true` if this operator is `*` + +#### quoted + +```rust title="unary_quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/op.nr#L48-L50 + + +Returns this operator as a `Quoted` value. + +### Trait Implementations + +```rust +impl Eq for UnaryOp +impl Hash for UnaryOp +``` + +### BinaryOp + +Represents a binary operator. One of `+`, `-`, `*`, `/`, `%`, `==`, `!=`, `<`, `<=`, `>`, `>=`, `&`, `|`, `^`, `>>`, or `<<`. + +### Methods + +#### is_add + +```rust title="is_add" showLineNumbers +pub fn is_add(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L86-L88 + + +`true` if this operator is `+` + +#### is_subtract + +```rust title="is_subtract" showLineNumbers +pub fn is_subtract(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L92-L94 + + +`true` if this operator is `-` + +#### is_multiply + +```rust title="is_multiply" showLineNumbers +pub fn is_multiply(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L98-L100 + + +`true` if this operator is `*` + +#### is_divide + +```rust title="is_divide" showLineNumbers +pub fn is_divide(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L104-L106 + + +`true` if this operator is `/` + +#### is_modulo + +```rust title="is_modulo" showLineNumbers +pub fn is_modulo(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L176-L178 + + +`true` if this operator is `%` + +#### is_equal + +```rust title="is_equal" showLineNumbers +pub fn is_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L110-L112 + + +`true` if this operator is `==` + +#### is_not_equal + +```rust title="is_not_equal" showLineNumbers +pub fn is_not_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L116-L118 + + +`true` if this operator is `!=` + +#### is_less_than + +```rust title="is_less_than" showLineNumbers +pub fn is_less_than(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L122-L124 + + +`true` if this operator is `<` + +#### is_less_than_or_equal + +```rust title="is_less_than_or_equal" showLineNumbers +pub fn is_less_than_or_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L128-L130 + + +`true` if this operator is `<=` + +#### is_greater_than + +```rust title="is_greater_than" showLineNumbers +pub fn is_greater_than(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L134-L136 + + +`true` if this operator is `>` + +#### is_greater_than_or_equal + +```rust title="is_greater_than_or_equal" showLineNumbers +pub fn is_greater_than_or_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L140-L142 + + +`true` if this operator is `>=` + +#### is_and + +```rust title="is_and" showLineNumbers +pub fn is_and(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L146-L148 + + +`true` if this operator is `&` + +#### is_or + +```rust title="is_or" showLineNumbers +pub fn is_or(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L152-L154 + + +`true` if this operator is `|` + +#### is_shift_right + +```rust title="is_shift_right" showLineNumbers +pub fn is_shift_right(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L164-L166 + + +`true` if this operator is `>>` + +#### is_shift_left + +```rust title="is_shift_right" showLineNumbers +pub fn is_shift_right(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L164-L166 + + +`true` if this operator is `<<` + +#### quoted + +```rust title="binary_quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/op.nr#L182-L184 + + +Returns this operator as a `Quoted` value. + +### Trait Implementations + +```rust +impl Eq for BinaryOp +impl Hash for BinaryOp +``` diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/quoted.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/quoted.md new file mode 100644 index 00000000000..d7acf23bc07 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/quoted.md @@ -0,0 +1,141 @@ +--- +title: Quoted +--- + +`std::meta::quoted` contains methods on the built-in `Quoted` type which represents +quoted token streams and is the result of the `quote { ... }` expression. + +## Methods + +### as_expr + +```rust title="as_expr" showLineNumbers +pub comptime fn as_expr(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L6-L8 + + +Parses the quoted token stream as an expression. Returns `Option::none()` if +the expression failed to parse. + +Example: + +```rust title="as_expr_example" showLineNumbers +#[test] + fn test_expr_as_function_call() { + comptime + { + let expr = quote { foo(42) }.as_expr().unwrap(); + let (_function, args) = expr.as_function_call().unwrap(); + assert_eq(args.len(), 1); + assert_eq(args[0].as_integer().unwrap(), (42, false)); + } + } +``` +> Source code: test_programs/noir_test_success/comptime_expr/src/main.nr#L360-L371 + + +### as_module + +```rust title="as_module" showLineNumbers +pub comptime fn as_module(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L11-L13 + + +Interprets this token stream as a module path leading to the name of a module. +Returns `Option::none()` if the module isn't found or this token stream cannot be parsed as a path. + +Example: + +```rust title="as_module_example" showLineNumbers +mod baz { + pub mod qux {} +} + +#[test] +fn as_module_test() { + comptime { + let my_mod = quote { baz::qux }.as_module().unwrap(); + assert_eq(my_mod.name(), quote { qux }); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_module/src/main.nr#L115-L127 + + +### as_trait_constraint + +```rust title="as_trait_constraint" showLineNumbers +pub comptime fn as_trait_constraint(self) -> TraitConstraint {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L16-L18 + + +Interprets this token stream as a trait constraint (without an object type). +Note that this function panics instead of returning `Option::none()` if the token +stream does not parse and resolve to a valid trait constraint. + +Example: + +```rust title="implements_example" showLineNumbers +pub fn function_with_where(_x: T) +where + T: SomeTrait, +{ + comptime { + let t = quote { T }.as_type(); + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + assert(t.implements(some_trait_i32)); + + assert(t.get_trait_impl(some_trait_i32).is_none()); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L160-L173 + + +### as_type + +```rust title="as_type" showLineNumbers +pub comptime fn as_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L21-L23 + + +Interprets this token stream as a resolved type. Panics if the token +stream doesn't parse to a type or if the type isn't a valid type in scope. + +```rust title="implements_example" showLineNumbers +pub fn function_with_where(_x: T) +where + T: SomeTrait, +{ + comptime { + let t = quote { T }.as_type(); + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + assert(t.implements(some_trait_i32)); + + assert(t.get_trait_impl(some_trait_i32).is_none()); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L160-L173 + + +### tokens + +```rust title="tokens" showLineNumbers +pub comptime fn tokens(self) -> [Quoted] {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L26-L28 + + +Returns a slice of the individual tokens that form this token stream. + +## Trait Implementations + +```rust +impl Eq for Quoted +impl Hash for Quoted +``` diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/struct_def.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/struct_def.md new file mode 100644 index 00000000000..fd609942f4e --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/struct_def.md @@ -0,0 +1,177 @@ +--- +title: StructDefinition +--- + +`std::meta::struct_def` contains methods on the built-in `StructDefinition` type. +This type corresponds to `struct Name { field1: Type1, ... }` items in the source program. + +## Methods + +### add_attribute + +```rust title="add_attribute" showLineNumbers +pub comptime fn add_attribute(self, attribute: str) {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L3-L5 + + +Adds an attribute to the struct. + +### add_generic + +```rust title="add_generic" showLineNumbers +pub comptime fn add_generic(self, generic_name: str) -> Type {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L8-L10 + + +Adds an generic to the struct. Returns the new generic type. +Errors if the given generic name isn't a single identifier or if +the struct already has a generic with the same name. + +This method should be used carefully, if there is existing code referring +to the struct type it may be checked before this function is called and +see the struct with the original number of generics. This method should +thus be preferred to use on code generated from other macros and structs +that are not used in function signatures. + +Example: + +```rust title="add-generic-example" showLineNumbers +comptime fn add_generic(s: StructDefinition) { + assert_eq(s.generics().len(), 0); + let new_generic = s.add_generic("T"); + + let generics = s.generics(); + assert_eq(generics.len(), 1); + assert_eq(generics[0], new_generic); + } +``` +> Source code: test_programs/compile_success_empty/comptime_struct_definition/src/main.nr#L35-L44 + + +### as_type + +```rust title="as_type" showLineNumbers +pub comptime fn as_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L15-L17 + + +Returns this struct as a type in the source program. If this struct has +any generics, the generics are also included as-is. + +### generics + +```rust title="generics" showLineNumbers +pub comptime fn generics(self) -> [Type] {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L26-L28 + + +Returns each generic on this struct. + +Example: + +``` +#[example] +struct Foo { + bar: [T; 2], + baz: Baz, +} + +comptime fn example(foo: StructDefinition) { + assert_eq(foo.generics().len(), 2); + + // Fails because `T` isn't in scope + // let t = quote { T }.as_type(); + // assert_eq(foo.generics()[0], t); +} +``` + +### fields + +```rust title="fields" showLineNumbers +pub comptime fn fields(self) -> [(Quoted, Type)] {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L33-L35 + + +Returns each field of this struct as a pair of (field name, field type). + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +pub comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L20-L22 + + +Returns true if this struct has a custom attribute with the given name. + +### module + +```rust title="module" showLineNumbers +pub comptime fn module(self) -> Module {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L38-L40 + + +Returns the module where the struct is defined. + +### name + +```rust title="name" showLineNumbers +pub comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L43-L45 + + +Returns the name of this struct + +Note that the returned quoted value will be just the struct name, it will +not be the full path to the struct, nor will it include any generics. + +### set_fields + +```rust title="set_fields" showLineNumbers +pub comptime fn set_fields(self, new_fields: [(Quoted, Type)]) {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L52-L54 + + +Sets the fields of this struct to the given fields list where each element +is a pair of the field's name and the field's type. Expects each field name +to be a single identifier. Note that this will override any previous fields +on this struct. If those should be preserved, use `.fields()` to retrieve the +current fields on the struct type and append the new fields from there. + +Example: + +```rust +// Change this struct to: +// struct Foo { +// a: u32, +// b: i8, +// } +#[mangle_fields] +struct Foo { x: Field } + +comptime fn mangle_fields(s: StructDefinition) { + s.set_fields(&[ + (quote { a }, quote { u32 }.as_type()), + (quote { b }, quote { i8 }.as_type()), + ]); +} +``` + +## Trait Implementations + +```rust +impl Eq for StructDefinition +impl Hash for StructDefinition +``` + +Note that each struct is assigned a unique ID internally and this is what is used for +equality and hashing. So even structs with identical generics and fields may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/trait_constraint.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/trait_constraint.md new file mode 100644 index 00000000000..3106f732b5a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/trait_constraint.md @@ -0,0 +1,17 @@ +--- +title: TraitConstraint +--- + +`std::meta::trait_constraint` contains methods on the built-in `TraitConstraint` type which represents +a trait constraint that can be used to search for a trait implementation. This is similar +syntactically to just the trait itself, but can also contain generic arguments. E.g. `Eq`, `Default`, +`BuildHasher`. + +This type currently has no public methods but it can be used alongside `Type` in `implements` or `get_trait_impl`. + +## Trait Implementations + +```rust +impl Eq for TraitConstraint +impl Hash for TraitConstraint +``` diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/trait_def.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/trait_def.md new file mode 100644 index 00000000000..e661d3af7f1 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/trait_def.md @@ -0,0 +1,26 @@ +--- +title: TraitDefinition +--- + +`std::meta::trait_def` contains methods on the built-in `TraitDefinition` type. This type +represents trait definitions such as `trait Foo { .. }` at the top-level of a program. + +## Methods + +### as_trait_constraint + +```rust title="as_trait_constraint" showLineNumbers +pub comptime fn as_trait_constraint(_self: Self) -> TraitConstraint {} +``` +> Source code: noir_stdlib/src/meta/trait_def.nr#L6-L8 + + +Converts this trait into a trait constraint. If there are any generics on this +trait, they will be kept as-is without instantiating or replacing them. + +## Trait Implementations + +```rust +impl Eq for TraitDefinition +impl Hash for TraitDefinition +``` diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/trait_impl.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/trait_impl.md new file mode 100644 index 00000000000..a527617c1e6 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/trait_impl.md @@ -0,0 +1,60 @@ +--- +title: TraitImpl +--- + +`std::meta::trait_impl` contains methods on the built-in `TraitImpl` type which represents a trait +implementation such as `impl Foo for Bar { ... }`. + +## Methods + +### trait_generic_args + +```rust title="trait_generic_args" showLineNumbers +pub comptime fn trait_generic_args(self) -> [Type] {} +``` +> Source code: noir_stdlib/src/meta/trait_impl.nr#L3-L5 + + +Returns any generic arguments on the trait of this trait implementation, if any. + +```rs +impl Foo for Bar { ... } + +comptime { + let bar_type = quote { Bar }.as_type(); + let foo = quote { Foo }.as_trait_constraint(); + + let my_impl: TraitImpl = bar_type.get_trait_impl(foo).unwrap(); + + let generics = my_impl.trait_generic_args(); + assert_eq(generics.len(), 2); + + assert_eq(generics[0], quote { i32 }.as_type()); + assert_eq(generics[1], quote { Field }.as_type()); +} +``` + +### methods + +```rust title="methods" showLineNumbers +pub comptime fn methods(self) -> [FunctionDefinition] {} +``` +> Source code: noir_stdlib/src/meta/trait_impl.nr#L8-L10 + + +Returns each method in this trait impl. + +Example: + +```rs +comptime { + let i32_type = quote { i32 }.as_type(); + let eq = quote { Eq }.as_trait_constraint(); + + let impl_eq_for_i32: TraitImpl = i32_type.get_trait_impl(eq).unwrap(); + let methods = impl_eq_for_i32.methods(); + + assert_eq(methods.len(), 1); + assert_eq(methods[0].name(), quote { eq }); +} +``` diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/typ.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/typ.md new file mode 100644 index 00000000000..90222c222f5 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/typ.md @@ -0,0 +1,264 @@ +--- +title: Type +--- + +`std::meta::typ` contains methods on the built-in `Type` type used for representing +a type in the source program. + +## Functions + +```rust title="fresh_type_variable" showLineNumbers +pub comptime fn fresh_type_variable() -> Type {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L57-L59 + + +Creates and returns an unbound type variable. This is a special kind of type internal +to type checking which will type check with any other type. When it is type checked +against another type it will also be set to that type. For example, if `a` is a type +variable and we have the type equality `(a, i32) = (u8, i32)`, the compiler will set +`a` equal to `u8`. + +Unbound type variables will often be rendered as `_` while printing them. Bound type +variables will appear as the type they are bound to. + +This can be used in conjunction with functions which internally perform type checks +such as `Type::implements` or `Type::get_trait_impl` to potentially grab some of the types used. + +Note that calling `Type::implements` or `Type::get_trait_impl` on a type variable will always +fail. + +Example: + +```rust title="serialize-setup" showLineNumbers +trait Serialize {} + +impl Serialize<1> for Field {} + +impl Serialize for [T; N] +where + T: Serialize, +{} + +impl Serialize for (T, U) +where + T: Serialize, + U: Serialize, +{} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L14-L29 + +```rust title="fresh-type-variable-example" showLineNumbers +let typevar1 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar1> }.as_trait_constraint(); + let field_type = quote { Field }.as_type(); + + // Search for a trait impl (binding typevar1 to 1 when the impl is found): + assert(field_type.implements(constraint)); + + // typevar1 should be bound to the "1" generic now: + assert_eq(typevar1.as_constant().unwrap(), 1); + + // If we want to do the same with a different type, we need to + // create a new type variable now that `typevar1` is bound + let typevar2 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar2> }.as_trait_constraint(); + let array_type = quote { [(Field, Field); 5] }.as_type(); + assert(array_type.implements(constraint)); + + // Now typevar2 should be bound to the serialized pair size 2 times the array length 5 + assert_eq(typevar2.as_constant().unwrap(), 10); +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L129-L149 + + +## Methods + +### as_array + +```rust title="as_array" showLineNumbers +pub comptime fn as_array(self) -> Option<(Type, Type)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L76-L78 + + +If this type is an array, return a pair of (element type, size type). + +Example: + +```rust +comptime { + let array_type = quote { [Field; 3] }.as_type(); + let (field_type, three_type) = array_type.as_array().unwrap(); + + assert(field_type.is_field()); + assert_eq(three_type.as_constant().unwrap(), 3); +} +``` + +### as_constant + +```rust title="as_constant" showLineNumbers +pub comptime fn as_constant(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L83-L85 + + +If this type is a constant integer (such as the `3` in the array type `[Field; 3]`), +return the numeric constant. + +### as_integer + +```rust title="as_integer" showLineNumbers +pub comptime fn as_integer(self) -> Option<(bool, u8)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L90-L92 + + +If this is an integer type, return a boolean which is `true` +if the type is signed, as well as the number of bits of this integer type. + +### as_mutable_reference + +```rust title="as_mutable_reference" showLineNumbers +comptime fn as_mutable_reference(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L96-L98 + + +If this is a mutable reference type `&mut T`, returns the mutable type `T`. + +### as_slice + +```rust title="as_slice" showLineNumbers +pub comptime fn as_slice(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L102-L104 + + +If this is a slice type, return the element type of the slice. + +### as_str + +```rust title="as_str" showLineNumbers +pub comptime fn as_str(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L108-L110 + + +If this is a `str` type, returns the length `N` as a type. + +### as_struct + +```rust title="as_struct" showLineNumbers +pub comptime fn as_struct(self) -> Option<(StructDefinition, [Type])> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L114-L116 + + +If this is a struct type, returns the struct in addition to +any generic arguments on this type. + +### as_tuple + +```rust title="as_tuple" showLineNumbers +pub comptime fn as_tuple(self) -> Option<[Type]> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L120-L122 + + +If this is a tuple type, returns each element type of the tuple. + +### get_trait_impl + +```rust title="get_trait_impl" showLineNumbers +pub comptime fn get_trait_impl(self, constraint: TraitConstraint) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L143-L145 + + +Retrieves the trait implementation that implements the given +trait constraint for this type. If the trait constraint is not +found, `None` is returned. Note that since the concrete trait implementation +for a trait constraint specified from a `where` clause is unknown, +this function will return `None` in these cases. If you only want to know +whether a type implements a trait, use `implements` instead. + +Example: + +```rust +comptime { + let field_type = quote { Field }.as_type(); + let default = quote { Default }.as_trait_constraint(); + + let the_impl: TraitImpl = field_type.get_trait_impl(default).unwrap(); + assert(the_impl.methods().len(), 1); +} +``` + +### implements + +```rust title="implements" showLineNumbers +pub comptime fn implements(self, constraint: TraitConstraint) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L166-L168 + + +`true` if this type implements the given trait. Note that unlike +`get_trait_impl` this will also return true for any `where` constraints +in scope. + +Example: + +```rust +fn foo() where T: Default { + comptime { + let field_type = quote { Field }.as_type(); + let default = quote { Default }.as_trait_constraint(); + assert(field_type.implements(default)); + + let t = quote { T }.as_type(); + assert(t.implements(default)); + } +} +``` + +### is_bool + +```rust title="is_bool" showLineNumbers +pub comptime fn is_bool(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L172-L174 + + +`true` if this type is `bool`. + +### is_field + +```rust title="is_field" showLineNumbers +pub comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L178-L180 + + +`true` if this type is `Field`. + +### is_unit + +```rust title="is_unit" showLineNumbers +comptime fn is_unit(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L184-L186 + + +`true` if this type is the unit `()` type. + +## Trait Implementations + +```rust +impl Eq for Type +impl Hash for Type +``` +Note that this is syntactic equality, this is not the same as whether two types will type check +to be the same type. Unless type inference or generics are being used however, users should not +typically have to worry about this distinction unless `std::meta::typ::fresh_type_variable` is used. diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/typed_expr.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/typed_expr.md new file mode 100644 index 00000000000..0db7dbfef61 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/typed_expr.md @@ -0,0 +1,27 @@ +--- +title: TypedExpr +--- + +`std::meta::typed_expr` contains methods on the built-in `TypedExpr` type for resolved and type-checked expressions. + +## Methods + +### get_type + +```rust title="as_function_definition" showLineNumbers +pub comptime fn as_function_definition(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typed_expr.nr#L7-L9 + + +If this expression refers to a function definitions, returns it. Otherwise returns `Option::none()`. + +### get_type + +```rust title="get_type" showLineNumbers +pub comptime fn get_type(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typed_expr.nr#L13-L15 + + +Returns the type of the expression, or `Option::none()` if there were errors when the expression was previously resolved. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/unresolved_type.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/unresolved_type.md new file mode 100644 index 00000000000..2826ec5ec0f --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/meta/unresolved_type.md @@ -0,0 +1,57 @@ +--- +title: UnresolvedType +--- + +`std::meta::unresolved_type` contains methods on the built-in `UnresolvedType` type for the syntax of types. + +## Methods + +### as_mutable_reference + +```rust title="as_mutable_reference" showLineNumbers +comptime fn as_mutable_reference(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L8-L10 + + +If this is a mutable reference type `&mut T`, returns the mutable type `T`. + +### as_slice + +```rust title="as_slice" showLineNumbers +comptime fn as_slice(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L14-L16 + + +If this is a slice `&[T]`, returns the element type `T`. + +### is_bool + +```rust title="is_bool" showLineNumbers +comptime fn is_bool(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L20-L22 + + +Returns `true` if this type is `bool`. + +### is_field + +```rust title="is_field" showLineNumbers +pub comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L26-L28 + + +Returns true if this type refers to the Field type. + +### is_unit + +```rust title="is_unit" showLineNumbers +comptime fn is_unit(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L32-L34 + + +Returns true if this type is the unit `()` type. diff --git a/docs/versioned_docs/version-v0.36.0/noir/standard_library/options.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/noir/standard_library/recursion.mdx b/docs/versioned_docs/version-v0.36.0/noir/standard_library/recursion.mdx new file mode 100644 index 00000000000..60414a2fa51 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/recursion.mdx @@ -0,0 +1,85 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, verify_proof] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox'; + +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) {} +``` + + + +## Example usage + +```rust + +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, + proof, + public_inputs, + key_hash + ); + + std::verify_proof( + verification_key, + proof_b, + public_inputs, + 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.36.0/noir/standard_library/traits.md b/docs/versioned_docs/version-v0.36.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..ee20f9cd949 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/noir/standard_library/traits.md @@ -0,0 +1,628 @@ +--- +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 +pub trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L4-L8 + + +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 +pub 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#L28-L119 + + +#### 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 +pub 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-L26 + + +`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 +pub trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L4-L8 + + +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 +pub trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L210-L214 + + +`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 +pub trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +pub trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L60-L64 + +```rust title="mul-trait" showLineNumbers +pub trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L119-L123 + +```rust title="div-trait" showLineNumbers +pub trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L178-L182 + + +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 +pub trait Rem { + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L237-L241 + + +`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 +pub trait Neg { + fn neg(self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L290-L294 + + +`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#L296-L323 + + +### `std::ops::Not` + +```rust title="not-trait" showLineNumbers +pub 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-L60 + + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +pub trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L62-L66 + +```rust title="bitand-trait" showLineNumbers +pub trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L121-L125 + +```rust title="bitxor-trait" showLineNumbers +pub trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L180-L184 + + +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 +pub trait Shl { + fn shl(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L239-L243 + +```rust title="shr-trait" showLineNumbers +pub trait Shr { + fn shr(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L292-L296 + + +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 } } +``` + +--- + +## `std::append` + +### `std::append::Append` + +`Append` can abstract over types that can be appended to - usually container types: + +```rust title="append-trait" showLineNumbers +pub trait Append { + fn empty() -> Self; + fn append(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/append.nr#L9-L14 + + +`Append` requires two methods: + +- `empty`: Constructs an empty value of `Self`. +- `append`: Append two values together, returning the result. + +Additionally, it is expected that for any implementation: + +- `T::empty().append(x) == x` +- `x.append(T::empty()) == x` + +Implementations: +```rust +impl Append for [T] +impl Append for Quoted +``` diff --git a/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..252d72a0b71 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,138 @@ +# BarretenbergBackend + +## Implements + +- [`Backend`](../index.md#backend) +- [`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) + +## Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `backend` | `UltraPlonkBackend` | - | + +## 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); +``` + +*** + +### getVerificationKey() + +```ts +getVerificationKey(): Promise +``` + +#### Returns + +`Promise`\<`Uint8Array`\> + +*** + +### 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.36.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md new file mode 100644 index 00000000000..500276ea748 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkBackend.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkBackend.md new file mode 100644 index 00000000000..204aaa18db6 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkBackend.md @@ -0,0 +1,114 @@ +# UltraHonkBackend + +## Implements + +- [`Backend`](../index.md#backend) +- [`Backend`](../index.md#backend) + +## Constructors + +### new UltraHonkBackend(acirCircuit, options) + +```ts +new UltraHonkBackend(acirCircuit, options): UltraHonkBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | `CompiledCircuit` | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`UltraHonkBackend`](UltraHonkBackend.md) + +## Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `backend` | `UltraHonkBackend` | - | + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +*** + +### generateProof() + +```ts +generateProof(compressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `compressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<`ProofData`\> + +*** + +### generateRecursiveProofArtifacts() + +```ts +generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | +| `numOfPublicInputs` | `number` | + +#### Returns + +`Promise`\<`object`\> + +*** + +### getVerificationKey() + +```ts +getVerificationKey(): Promise +``` + +#### Returns + +`Promise`\<`Uint8Array`\> + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`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.36.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkVerifier.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkVerifier.md new file mode 100644 index 00000000000..aee9460153f --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/classes/UltraHonkVerifier.md @@ -0,0 +1,58 @@ +# UltraHonkVerifier + +## Constructors + +### new UltraHonkVerifier(options) + +```ts +new UltraHonkVerifier(options): UltraHonkVerifier +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`UltraHonkVerifier`](UltraHonkVerifier.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.36.0/reference/NoirJS/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 00000000000..4699e16dee6 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,42 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | +| [BarretenbergVerifier](classes/BarretenbergVerifier.md) | - | +| [UltraHonkBackend](classes/UltraHonkBackend.md) | - | +| [UltraHonkVerifier](classes/UltraHonkVerifier.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; +``` + +*** + +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.36.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..1837bd4e205 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,19 @@ +# BackendOptions + +```ts +type BackendOptions: object; +``` + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `crsPath` | `string` | **Description**

Path to download CRS files | +| `memory` | `object` | **Description**

Initial and Maximum memory to be alloted to the backend worker | +| `memory.initial` | `number` | - | +| `memory.maximum` | `number` | - | +| `threads` | `number` | **Description**

Number of threads to run the backend worker on | + +*** + +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.36.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..8ecf05c0163 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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":"doc","id":"reference/NoirJS/backend_barretenberg/classes/UltraHonkBackend","label":"UltraHonkBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/UltraHonkVerifier","label":"UltraHonkVerifier"}]},{"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.36.0/reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..ead255bc504 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,52 @@ +# Noir + +## Constructors + +### new Noir(circuit) + +```ts +new Noir(circuit): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### 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) +``` + +*** + +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.36.0/reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.36.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.36.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.36.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.36.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.36.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.36.0/reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..4de7a696991 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,47 @@ +# 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. | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +## References + +### CompiledCircuit + +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.36.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md new file mode 100644 index 00000000000..e8c2f4aef3d --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..4796b5abaa8 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_wasm/.nojekyll b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_wasm/functions/compile.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_wasm/index.md b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.36.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/_category_.json b/docs/versioned_docs/version-v0.36.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v0.36.0/reference/debugger/_category_.json b/docs/versioned_docs/version-v0.36.0/reference/debugger/_category_.json new file mode 100644 index 00000000000..186aeb3654e --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/debugger/debugger_known_limitations.md b/docs/versioned_docs/version-v0.36.0/reference/debugger/debugger_known_limitations.md new file mode 100644 index 00000000000..936d416ac4b --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/debugger/debugger_repl.md b/docs/versioned_docs/version-v0.36.0/reference/debugger/debugger_repl.md new file mode 100644 index 00000000000..46e2011304e --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/debugger/debugger_vscode.md b/docs/versioned_docs/version-v0.36.0/reference/debugger/debugger_vscode.md new file mode 100644 index 00000000000..c027332b3b0 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/reference/nargo_commands.md b/docs/versioned_docs/version-v0.36.0/reference/nargo_commands.md new file mode 100644 index 00000000000..db1884afee2 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/nargo_commands.md @@ -0,0 +1,297 @@ +--- +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 check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo debug`↴](#nargo-debug) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `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 +* `debug` — Executes a circuit in debug mode +* `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 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 ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + + +## `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 ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + + +## `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 + +Defaults to the name of the package being executed. + +###### **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 ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo debug` + +Executes a circuit in debug mode + +**Usage:** `nargo debug [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 +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code +* `--acir-mode` — Force ACIR output (disabling instrumentation) +* `--skip-instrumentation ` — Disable vars debug instrumentation (enabled by default) + + Possible values: `true`, `false` + + + + +## `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 ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code +* `--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 ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + + +## `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.36.0/reference/noir_codegen.md b/docs/versioned_docs/version-v0.36.0/reference/noir_codegen.md new file mode 100644 index 00000000000..e4c362f9610 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/reference/noir_codegen.md @@ -0,0 +1,116 @@ +--- +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](../getting_started/noir_installation.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"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"}},"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.36.0/tooling/debugger.md b/docs/versioned_docs/version-v0.36.0/tooling/debugger.md new file mode 100644 index 00000000000..200b5fc423a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/tooling/debugger.md @@ -0,0 +1,26 @@ +--- +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/noir_installation.md) and vscode-noir: + +- Noir & Nargo ≥0.28.0 +- Noir's VS Code extension ≥0.0.11 + +:::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.36.0/tooling/language_server.md b/docs/versioned_docs/version-v0.36.0/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v0.36.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.36.0/tooling/testing.md b/docs/versioned_docs/version-v0.36.0/tooling/testing.md new file mode 100644 index 00000000000..866677da567 --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/tooling/testing.md @@ -0,0 +1,79 @@ +--- +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); +} +``` + +The string given to `should_fail_with` doesn't need to exactly match the failure reason, it just needs to be a substring of it: + +```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 = "airspeed velocity")] +fn test_bridgekeeper() { + main(32); +} +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.36.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v0.36.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..6e69ea0bbed --- /dev/null +++ b/docs/versioned_docs/version-v0.36.0/tutorials/noirjs_app.md @@ -0,0 +1,366 @@ +--- +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.31.x matches `noir_js@0.31.x`, etc. + +In this guide, we will be pinned to 0.31.0. + +::: + +Before we start, we want to make sure we have Node, Nargo and the Barretenberg proving system (`bb`) 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/quick_start.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 +``` + +Follow the instructions on [this page](https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/cpp/src/barretenberg/bb#installation) to install `bb`. +Version 0.41.0 is compatible with `nargo` version 0.31.0, which you can install with `bbup -v 0.41.0` once `bbup` is installed. + +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: + +```bash +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: + +```bash +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/quick_start.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'; +import fs from 'fs'; +import path from 'path'; + +const wasmContentTypePlugin = { + name: 'wasm-content-type-plugin', + configureServer(server) { + server.middlewares.use(async (req, res, next) => { + if (req.url.endsWith('.wasm')) { + res.setHeader('Content-Type', 'application/wasm'); + const newPath = req.url.replace('deps', 'dist'); + const targetPath = path.join(__dirname, newPath); + const wasmContent = fs.readFileSync(targetPath); + return res.end(wasmContent); + } + next(); + }); + }, +}; + +export default defineConfig(({ command }) => { + if (command === 'serve') { + return { + build: { + target: 'esnext', + rollupOptions: { + external: ['@aztec/bb.js'] + } + }, + optimizeDeps: { + esbuildOptions: { + target: 'esnext' + } + }, + plugins: [ + copy({ + targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], + copySync: true, + hook: 'buildStart', + }), + command === 'serve' ? wasmContentTypePlugin : [], + ], + }; + } + + return {}; +}); +``` + +#### 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.31.0 @noir-lang/noir_js@0.31.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 +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 😢 + +:::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); +// } +``` + +:::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 { witness } = await noir.execute(input); +const proof = await backend.generateProof(witness); +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 isValid = await backend.verifyProof(proof); + +// or to cache and use the verification key: +// 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. + +## UltraHonk Backend + +Barretenberg has recently exposed a new UltraHonk backend. We can use UltraHonk in NoirJS after version 0.33.0. Everything will be the same as the tutorial above, except that the class we need to import will change: + +```js +import { UltraHonkBackend, UltraHonkVerifier as Verifier } from '@noir-lang/backend_barretenberg'; +``` + +The backend will then be instantiated as such: + +```js +const backend = new UltraHonkBackend(circuit); +``` + +Then all the commands to prove and verify your circuit will be same. + +The only feature currently unsupported with UltraHonk are [recursive proofs](../explainers/explainer-recursion.md). diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/explainers/cspell.json b/docs/versioned_docs/version-v1.0.0-beta.0/explainers/cspell.json new file mode 100644 index 00000000000..c60b0a597b1 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/explainers/cspell.json @@ -0,0 +1,5 @@ +{ + "words": [ + "Cryptdoku" + ] +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/explainers/explainer-oracle.md b/docs/versioned_docs/version-v1.0.0-beta.0/explainers/explainer-oracle.md new file mode 100644 index 00000000000..821e1f95c04 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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 an 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 match 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-v1.0.0-beta.0/explainers/explainer-recursion.md b/docs/versioned_docs/version-v1.0.0-beta.0/explainers/explainer-recursion.md new file mode 100644 index 00000000000..df8529ef4e0 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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.mdx), 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-v1.0.0-beta.0/explainers/explainer-writing-noir.md b/docs/versioned_docs/version-v1.0.0-beta.0/explainers/explainer-writing-noir.md new file mode 100644 index 00000000000..3ce4245dc45 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/explainers/explainer-writing-noir.md @@ -0,0 +1,177 @@ +--- +title: Thinking in Circuits +description: Considerations when writing Noir programs +keywords: [Noir, programming, rust] +tags: [Optimization] +sidebar_position: 0 +--- + + +This article intends to set you up with key concepts essential for writing more viable applications that use zero knowledge proofs, namely around efficient circuits. + +## Context - 'Efficient' is subjective + +When writing a web application for a performant computer with high-speed internet connection, writing efficient code sometimes is seen as an afterthought only if needed. Large multiplications running at the innermost of nested loops may not even be on a dev's radar. +When writing firmware for a battery-powered microcontroller, you think of cpu cycles as rations to keep within a product's power budget. + +> Code is written to create applications that perform specific tasks within specific constraints + +And these constraints differ depending on where the compiled code is execute. + +### The Ethereum Virtual Machine (EVM) + +In scenarios where extremely low gas costs are required for an Ethereum application to be viable/competitive, Ethereum smart contract developers get into what is colloquially known as: "*gas golfing*". Finding the lowest execution cost of their compiled code (EVM bytecode) to achieve a specific task. + +The equivalent optimization task when writing zk circuits is affectionately referred to as "*gate golfing*", finding the lowest gate representation of the compiled Noir code. + +### Coding for circuits - a paradigm shift + +In zero knowledge cryptography, code is compiled to "circuits" consisting of arithmetic gates, and gate count is the significant cost. Depending on the proving system this is linearly proportionate to proving time, and so from a product point this should be kept as low as possible. + +Whilst writing efficient code for web apps and Solidity has a few key differences, writing efficient circuits have a different set of considerations. It is a bit of a paradigm shift, like writing code for GPUs for the first time... + +For example, drawing a circle at (0, 0) of radius `r`: +- For a single CPU thread, +``` +for theta in 0..2*pi { + let x = r * cos(theta); + let y = r * sin(theta); + draw(x, y); +} // note: would do 0 - pi/2 and draw +ve/-ve x and y. +``` + +- For GPUs (simultaneous parallel calls with x, y across image), +``` +if (x^2 + y^2 = r^2) { + draw(x, y); +} +``` + +([Related](https://www.youtube.com/watch?v=-P28LKWTzrI)) + +Whilst this CPU -> GPU does not translate to circuits exactly, it is intended to exemplify the difference in intuition when coding for different machine capabilities/constraints. + +### Context Takeaway + +For those coming from a primarily web app background, this article will explain what you need to consider when writing circuits. Furthermore, for those experienced writing efficient machine code, prepare to shift what you think is efficient 😬 + +## Translating from Rust + +For some applications using Noir, existing code might be a convenient starting point to then proceed to optimize the gate count of. + +:::note +Many valuable functions and algorithms have been written in more established languages (C/C++), and converted to modern ones (like Rust). +::: + +Fortunately for Noir developers, when needing a particular function a Rust implementation can be readily compiled into Noir with some key changes. While the compiler does a decent amount of optimizations, it won't be able to change code that has been optimized for clock-cycles into code optimized for arithmetic gates. + +A few things to do when converting Rust code to Noir: +- `println!` is not a macro, use `println` function (same for `assert_eq`) +- No early `return` in function. Use constrain via assertion instead +- No passing by reference. Remove `&` operator to pass by value (copy) +- No boolean operators (`&&`, `||`). Use bitwise operators (`&`, `|`) with boolean values +- No type `usize`. Use types `u8`, `u32`, `u64`, ... +- `main` return must be public, `pub` +- No `const`, use `global` +- Noir's LSP is your friend, so error message should be informative enough to resolve syntax issues. + +## Writing efficient Noir for performant products + +The following points help refine our understanding over time. + +:::note +A Noir program makes a statement that can be verified. +::: + +It compiles to a structure that represents the calculation, and can assert results within the calculation at any stage (via the `constrain` keyword). + +A Noir program compiles to an Abstract Circuit Intermediate Representation which is: + - Conceptually a tree structure + - Leaves (inputs) are the `Field` type + - Nodes contain arithmetic operations to combine them (gates) + - The root is the final result (return value) + +:::tip +The command `nargo info` shows the programs circuit size, and is useful to compare the value of changes made. +You can dig deeper and use the `--print-acir` param to take a closer look at individual ACIR opcodes, and the proving backend to see its gate count (eg for barretenberg, `bb gates -b ./target/program.json`). +::: + +### Use the `Field` type + +Since the native type of values in circuits are `Field`s, using them for variables in Noir means less gates converting them under the hood. +Some things to be mindful of when using a Field type for a regular integer value: +- A variable of type `Field` can be cast `as` an integer type (eg `u8`, `u64`) + - Note: this retains only the bits of the integer type. Eg a Field value of 260 as a `u8` becomes 4 +- For Field types arithmetic operations meaningfully overflow/underflow, yet for integer types they are checked according to their size +- Comparisons and bitwise operations do not exist for `Field`s, cast to an appropriately sized integer type when you need to + +:::tip +Where possible, use `Field` type for values. Using smaller value types, and bit-packing strategies, will result in MORE gates +::: + + +### Use Arithmetic over non-arithmetic operations + +Since circuits are made of arithmetic gates, the cost of arithmetic operations tends to be one gate. Whereas for procedural code, they represent several clock cycles. + +Inversely, non-arithmetic operators are achieved with multiple gates, vs 1 clock cycle for procedural code. + +| (cost\op) | arithmetic
(`*`, `+`) | bit-wise ops
(eg `<`, `\|`, `>>`) | +| - | - | - | +| **cycles** | 10+ | 1 | +| **gates** | 1 | 10+ | + +Bit-wise operations (e.g. bit shifts `<<` and `>>`), albeit commonly used in general programming and especially for clock cycle optimizations, are on the contrary expensive in gates when performed within circuits. + +Translate away from bit shifts when writing constrained functions for the best performance. + +On the flip side, feel free to use bit shifts in unconstrained functions and tests if necessary, as they are executed outside of circuits and does not induce performance hits. + +### Use static over dynamic values + +Another general theme that manifests in different ways is that static reads are represented with less gates than dynamic ones. + +Reading from read-only memory (ROM) adds less gates than random-access memory (RAM), 2 vs ~3.25 due to the additional bounds checks. Arrays of fixed length (albeit used at a lower capacity), will generate less gates than dynamic storage. + +Related to this, if an index used to access an array is not known at compile time (ie unknown until run time), then ROM will be converted to RAM, expanding the gate count. + +:::tip +Use arrays and indices that are known at compile time where possible. +Using `assert_constant(i);` before an index, `i`, is used in an array will give a compile error if `i` is NOT known at compile time. +::: + +### Leverage unconstrained execution + +Constrained verification can leverage unconstrained execution, this is especially useful for operations that are represented by many gates. +Use an [unconstrained function](../noir/concepts/unconstrained.md) to perform gate-heavy calculations, then verify and constrain the result. + +Eg division generates more gates than multiplication, so calculating the quotient in an unconstrained function then constraining the product for the quotient and divisor (+ any remainder) equals the dividend will be more efficient. + +Use ` if is_unconstrained() { /`, to conditionally execute code if being called in an unconstrained vs constrained way. + +## Advanced + +Unless you're well into the depth of gate optimization, this advanced section can be ignored. + +### Combine arithmetic operations + +A Noir program can be honed further by combining arithmetic operators in a way that makes the most of each constraint of the backend proving system. This is in scenarios where the backend might not be doing this perfectly. + +Eg Barretenberg backend (current default for Noir) is a width-4 PLONKish constraint system +$ w_1*w_2*q_m + w_1*q_1 + w_2*q_2 + w_3*q_3 + w_4*q_4 + q_c = 0 $ + +Here we see there is one occurrence of witness 1 and 2 ($w_1$, $w_2$) being multiplied together, with addition to witnesses 1-4 ($w_1$ .. $w_4$) multiplied by 4 corresponding circuit constants ($q_1$ .. $q_4$) (plus a final circuit constant, $q_c$). + +Use `nargo info --print-acir`, to inspect the ACIR opcodes (and the proving system for gates), and it may present opportunities to amend the order of operations and reduce the number of constraints. + +#### Variable as witness vs expression + +If you've come this far and really know what you're doing at the equation level, a temporary lever (that will become unnecessary/useless over time) is: `std::as_witness`. This informs the compiler to save a variable as a witness not an expression. + +The compiler will mostly be correct and optimal, but this may help some near term edge cases that are yet to optimize. +Note: When used incorrectly it will create **less** efficient circuits (higher gate count). + +## References +- Guillaume's ["`Cryptdoku`" talk](https://www.youtube.com/watch?v=MrQyzuogxgg) (Jun'23) +- Tips from Tom, Jake and Zac. +- [Idiomatic Noir](https://www.vlayer.xyz/blog/idiomatic-noir-part-1-collections) blog post diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/getting_started/noir_installation.md b/docs/versioned_docs/version-v1.0.0-beta.0/getting_started/noir_installation.md new file mode 100644 index 00000000000..a5c7e649278 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/getting_started/noir_installation.md @@ -0,0 +1,106 @@ +--- +title: Standalone Noir Installation +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: 2 +--- + +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](#installing-noirup). + +## Setting up shell completions + +Once `nargo` is installed, you can [set up shell completions for it](setting_up_shell_completions). + +## 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-v1.0.0-beta.0/getting_started/project_breakdown.md b/docs/versioned_docs/version-v1.0.0-beta.0/getting_started/project_breakdown.md new file mode 100644 index 00000000000..e442e377040 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/getting_started/project_breakdown.md @@ -0,0 +1,159 @@ +--- +title: Project Breakdown +description: + 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, proof verification, private asset transfer] +sidebar_position: 1 +--- + +This section breaks down our hello world program from the previous section. + +## Anatomy of a Nargo Project + +Upon creating a new project with `nargo new` and building the in/output files with `nargo check` +commands, you would get a minimal Nargo project of the following structure: + + - src + - Prover.toml + - 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. + +### 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) +- `expression_width` (optional) - Sets the default backend expression width. This field will override the default backend expression width specified by the Noir compiler (currently set to width 4). + +#### 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 the inputs to the Noir program (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 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)`. + +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 + +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 execution by using the `--prover-name` or `-p` flags. + +This command looks for proof inputs in the default **Prover.toml** and generates the witness and saves it at `./target/foo.gz`: + +```bash +nargo execute foo +``` + +This command looks for proof inputs in the custom **OtherProver.toml** and generates the witness and saves it at `./target/bar.gz`: + +```bash +nargo execute -p OtherProver bar +``` + +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-v1.0.0-beta.0/getting_started/quick_start.md b/docs/versioned_docs/version-v1.0.0-beta.0/getting_started/quick_start.md new file mode 100644 index 00000000000..7deeae12fd9 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/getting_started/quick_start.md @@ -0,0 +1,126 @@ +--- +title: Quick Start +tags: [] +sidebar_position: 0 +--- + +## Installation + +### Noir + +The easiest way to develop with Noir is using Nargo the CLI tool. It provides you the ability to start new projects, compile, execute and test Noir programs from the terminal. + +You can use `noirup` the installation script to quickly install and update Nargo: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/refs/heads/main/install | bash +noirup +``` + +Once installed, you can [set up shell completions for the `nargo` command](setting_up_shell_completions). + +### Proving backend + +After installing Noir, we install a proving backend to work with our Noir programs. + +Proving backends provide you the abilities to generate proofs, verify proofs, generate smart contracts and more for your Noir programs. + +Different proving backends provide different tools for working with Noir programs, here we will use the [Barretenberg proving backend](https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg) developed by Aztec Labs as an example. + +You can use the `bbup` installation script to quickly install and update BB, Barretenberg's CLI tool: + +You can find the full list of proving backends compatible with Noir in Awesome Noir. + +```bash +curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/refs/heads/master/barretenberg/bbup/install | bash +bbup +``` + +For the full list of proving backends compatible with Noir, visit [Awesome Noir](https://github.com/noir-lang/awesome-noir/?tab=readme-ov-file#proving-backends). + +## Nargo + +Nargo provides the ability to initiate and execute Noir projects. Let's initialize the traditional `hello_world`: + +```sh +nargo new hello_world +``` + +Two files will be created. + +- `src/main.nr` contains a simple boilerplate circuit +- `Nargo.toml` contains environmental options, such as name, author, dependencies, and others. + +Glancing at _main.nr_ , we can see that inputs in Noir are private by default, but can be labeled public using the keyword `pub`. This means that we will _assert_ that we know a value `x` which is different from `y` without revealing `x`: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To learn more about private and public values, check the [Data Types](../noir/concepts/data_types/index.md) section. + +### Compiling and executing + +We can now use `nargo` to generate a _Prover.toml_ file, where our input values will be specified: + +```sh +cd hello_world +nargo check + +Let's feed some valid values into this file: + +```toml +x = "1" +y = "2" +``` + +We're now ready to compile and execute our Noir program. By default the `nargo execute` command will do both, and generate the `witness` that we need to feed to our proving backend: + +```sh +nargo execute +``` + +The witness corresponding to this execution will then be written to the file _./target/witness-name.gz_. + +The command also automatically compiles your Noir program if it was not already / was edited, which you may notice the compiled artifacts being written to the file _./target/hello_world.json_. + +With circuit compiled and witness generated, we're ready to prove. + +## Proving backend + +Different proving backends may provide different tools and commands to work with Noir programs. Here Barretenberg's `bb` CLI tool is used as an example: + +```sh +bb prove -b ./target/hello_world.json -w ./target/hello_world.gz -o ./target/proof +``` + +:::tip + +Naming can be confusing, specially as you pass them to the `bb` commands. If unsure, it won't hurt to delete the target folder and start anew to make sure you're using the most recent versions of the compiled circuit and witness. + +::: + +The proof is now generated in the `target` folder. To verify it we first need to compute the verification key from the compiled circuit, and use it to verify: + +```sh +bb write_vk -b ./target/hello_world.json -o ./target/vk +bb verify -k ./target/vk -p ./target/proof +``` + +:::info + +Notice that in order to verify a proof, the verifier knows nothing but the circuit, which is compiled and used to generate the verification key. This is obviously quite important: private inputs remain private. + +As for the public inputs, you may have noticed they haven't been specified. This behavior varies with each particular backend, but barretenberg typically attaches them to the proof. You can see them by parsing and splitting it. For example for if your public inputs are 32 bytes: + +```bash +head -c 32 ./target/proof | od -An -v -t x1 | tr -d $' \n' +``` + +::: + +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-v1.0.0-beta.0/getting_started/setting_up_shell_completions.md b/docs/versioned_docs/version-v1.0.0-beta.0/getting_started/setting_up_shell_completions.md new file mode 100644 index 00000000000..0447321cbab --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/getting_started/setting_up_shell_completions.md @@ -0,0 +1,87 @@ +--- +title: Setting up shell completions +tags: [] +sidebar_position: 3 +--- + +The `nargo` binary provides a command to generate shell completions: + +```bash +nargo generate-completion-script [shell] +``` + +where `shell` must be one of `bash`, `elvish`, `fish`, `powershell`, and `zsh`. + +Below we explain how to install them in some popular shells. + +## Installing Zsh Completions + +If you have `oh-my-zsh` installed, you might already have a directory of automatically loading completion scripts — `.oh-my-zsh/completions`. +If not, first create it: + +```bash +mkdir -p ~/.oh-my-zsh/completions` +``` + +Then copy the completion script to that directory: + +```bash +nargo generate-completion-script zsh > ~/.oh-my-zsh/completions/_nargo +``` + +Without `oh-my-zsh`, you’ll need to add a path for completion scripts to your function path, and turn on completion script auto-loading. +First, add these lines to `~/.zshrc`: + +```bash +fpath=(~/.zsh/completions $fpath) +autoload -U compinit +compinit +``` + +Next, create a directory at `~/.zsh/completions`: + +```bash +mkdir -p ~/.zsh/completions +``` + +Then copy the completion script to that directory: + +```bash +nargo generate-completion-script zsh > ~/.zsh/completions/_nargo +``` + +## Installing Bash Completions + +If you have [bash-completion](https://github.com/scop/bash-completion) installed, you can just copy the completion script to the `/usr/local/etc/bash_completion.d` directory: + +```bash +nargo generate-completion-script bash > /usr/local/etc/bash_completion.d/nargo +``` + +Without `bash-completion`, you’ll need to source the completion script directly. +First create a directory such as `~/.bash_completions/`: + +```bash +mkdir ~/.bash_completions/ +``` + +Copy the completion script to that directory: + +```bash +nargo generate-completion-script bash > ~/.bash_completions/nargo.bash +``` + +Then add the following line to `~/.bash_profile` or `~/.bashrc`: + + +```bash +source ~/.bash_completions/nargo.bash +``` + +## Installing Fish Completions + +Copy the completion script to any path listed in the environment variable `$fish_completion_path`. For example, a typical location is `~/.config/fish/completions/nargo.fish`: + +```bash +nargo generate-completion-script fish > ~/.config/fish/completions/nargo.fish +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/how_to/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/how_to/debugger/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/debugger/_category_.json new file mode 100644 index 00000000000..cc2cbb1c253 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/how_to/debugger/debugging_with_the_repl.md b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/debugger/debugging_with_the_repl.md new file mode 100644 index 00000000000..1d64dae3f37 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/how_to/debugger/debugging_with_vs_code.md b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/debugger/debugging_with_vs_code.md new file mode 100644 index 00000000000..a5858c1a5eb --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/how_to/how-to-oracles.md b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..0bb8743e361 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/how-to-oracles.md @@ -0,0 +1,275 @@ +--- +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.). + +## 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 function](../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 an 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); +} + +#[test] +fn test() { + let input = [4, 16]; + main(input); +} +``` + +:::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("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; +}); +``` + +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 +export type ForeignCallSingle = string; + +export type ForeignCallArray = string[]; + +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; +``` + +:::info Multidimensional Arrays + +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../reference/nargo_commands.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 +``` + +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.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. + +:::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`? 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) => { + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(input, 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-v1.0.0-beta.0/how_to/how-to-recursion.md b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/how-to-recursion.md new file mode 100644 index 00000000000..399e4d4b38a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/how-to-recursion.md @@ -0,0 +1,172 @@ +--- +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 `bb.js`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "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.mdx), 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. + +::: + +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)`, which we want to embed in another circuit recursively. For example when proving with the `bb` tool, we can use the `--recursive` CLI option to tell the backend that it should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example of 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 UltraPlonkBackend(circuit, { threads: 8 }, { recursive: true }) +``` + +:::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) +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), + recursive: new Noir(circuits.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 { witness: recursiveWitness } = await noir_programs.recursive.execute(recursiveInputs) +const recursiveProof = await backends.recursive.generateProof(recursiveWitness); +``` + +::: diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/how_to/how-to-solidity-verifier.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/how-to-solidity-verifier.mdx new file mode 100644 index 00000000000..da36b60920d --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/how-to-solidity-verifier.mdx @@ -0,0 +1,300 @@ +--- +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 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir is universal. The witness and the compiled program can be fed into a proving backend such as Aztec's [Barretenberg](https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg), which can then generate a verifier contract for deployment on blockchains. + +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. + +Although not strictly in the domain of Noir itself, this guide shows how to generate a Solidity Verifier with Barretenberg and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You will be using Barretenberg as your proving backend +- You will be using an EVM blockchain to verify your proof +- 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/quick_start.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 with Barretenberg 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 + +:::info[Which proving system to use?] + +Barretenberg currently provides two provers: `UltraPlonk` and `UltraHonk`. In a nutshell, `UltraHonk` is faster and uses less RAM, but its verifier contract is much more expensive. `UltraPlonk` is optimized for on-chain verification, but proving is more expensive. + +In any case, we provide instructions for both. Choose your poison ☠️ + +::: + +## Step 1 - Generate a contract + +This is by far the most straightforward step. Just run: + +```sh +nargo compile +``` + +This will compile your source code into a Noir build artifact to be stored in the `./target` directory. From here on, it's Barretenberg's work. You can generate the smart contract using the commands: + + + + +```sh +bb write_vk_ultra_keccak_honk -b ./target/.json +bb contract_ultra_honk +``` + + + + +```sh +bb write_vk -b ./target/.json +bb contract +``` + + + + +replacing `` with the name of your Noir project. A `Verifier.sol` contract is now in the target folder and can be deployed to any EVM blockchain acting as a verifier smart contract. + +You can find more information about `bb` and the default Noir proving backend on [this page](../getting_started/quick_start.md#proving-backend). + + +## 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 tell you the contract is too big to deploy on mainnet, or complain about a stack too deep: + +![Contract code too big](@site/static/img/how-tos/solidity_verifier_6.png) +![Stack too deep](@site/static/img/how-tos/solidity_verifier_8.png) + +To avoid this, you can just use some optimization. Open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract ready 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 composed on multiple contracts working together. Remix will take care of the dependencies for us so we can simply deploy the Verifier contract by selecting it and hitting "deploy": + + + + +![Deploying HonkVerifier](@site/static/img/how-tos/solidity_verifier_7.png) + + + + +![Deploying PlonkVerifier](@site/static/img/how-tos/solidity_verifier_9.png) + + + + +A contract will show up in the "Deployed Contracts" section. + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +First generate a proof with `bb`. We need a `Prover.toml` file for our inputs. Run: + +```bash +nargo check +``` + +This will generate a `Prover.toml` you can fill with the values you want to prove. We can now execute the circuit with `nargo` and then use the proving backend to prove: + + + + +```bash +nargo execute +bb prove_ultra_keccak_honk -b ./target/.json -w ./target/ -o ./target/proof +``` + +:::tip[Public inputs] +Barretenberg attaches the public inputs to the proof, which in this case it's not very useful. If you're up for some JS, `bb.js` has [a method for it](https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/ts/src/proof/index.ts), but in the CLI you can use this ugly snippet: + +```bash +cat ./target/proof | od -An -v -t x1 | tr -d $' \n' | sed 's/^.\{8\}//' | (read hex; echo "${hex:0:192}${hex:256}") +``` + +Beautiful. This assumes a circuit with one public input (32 bytes, for Barretenberg). For more inputs, you can just increment `hex:256` with 32 more bytes for each public input. + +::: + + + + +```bash +nargo execute +bb prove -b ./target/.json -w ./target/ -o ./target/proof +``` + + +:::tip[Public inputs] +Barretenberg attaches the public inputs to the proof, which in this case it's not very useful. If you're up for some JS, `bb.js` has [a method for it](https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/ts/src/proof/index.ts), but in the CLI you can use this ugly snippet: + +```bash +tail -c +33 ./target/proof | od -An -v -t x1 | tr -d $' \n' +``` + +Beautiful. This assumes a circuit with one public input (32 bytes, for Barretenberg). For more inputs, you can just add 32 more bytes for each public input to the `tail` command. + +::: + + + + +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): + +```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. + +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 + +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: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo +- BSC +- Blast L2 +- Avalanche C-Chain +- Mode +- Linea +- Moonbeam + +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-v1.0.0-beta.0/how_to/merkle-proof.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..0a128adb2de --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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] +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 + +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-v1.0.0-beta.0/how_to/using-devcontainers.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/index.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/index.mdx new file mode 100644 index 00000000000..5c116a73b3f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/index.mdx @@ -0,0 +1,76 @@ +--- +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'; +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + + + +Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of statements without revealing all inputs to the statements. You can read more about Zero-Knowledge Proofs [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-v1.0.0-beta.0/migration_notes.md b/docs/versioned_docs/version-v1.0.0-beta.0/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/assert.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/assert.md new file mode 100644 index 00000000000..2132de42072 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/assert.md @@ -0,0 +1,78 @@ +--- +title: Assert Function +description: + Learn about the `assert` and `static_assert` functions 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 or compile-time, respectively. +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); +``` + +There is also a special `static_assert` function that behaves like `assert`, +but that runs at compile-time. + +```rust +fn main(xs: [Field; 3]) { + let x = 2 + 2; + let y = 4; + static_assert(x == y, "expected 2 + 2 to equal 4"); + + // This passes since the length of `xs` is known at compile-time + static_assert(xs.len() == 3, "expected the input to have 3 elements"); +} +``` + +This function fails when passed a dynamic (run-time) argument: + +```rust +fn main(x : Field, y : Field) { + // this fails because `x` is not known at compile-time + static_assert(x == 2, "expected x to be known at compile-time and equal to 2"); + + let mut example_slice = &[]; + if y == 4 { + example_slice = example_slice.push_back(0); + } + + // This fails because the length of `example_slice` is not known at + // compile-time + let error_message = "expected an empty slice, known at compile-time"; + static_assert(example_slice.len() == 0, error_message); +} +``` + diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/comments.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/comptime.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/comptime.md new file mode 100644 index 00000000000..2ceb030c7e1 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/comptime.md @@ -0,0 +1,445 @@ +--- +title: Compile-time Code & Metaprogramming +description: Learn how to use metaprogramming in Noir to create macros or derive your own traits +keywords: [Noir, comptime, compile-time, metaprogramming, macros, quote, unquote] +sidebar_position: 15 +--- + +## Overview + +Metaprogramming in Noir is comprised of three parts: +1. `comptime` code +2. Quoting and unquoting +3. The metaprogramming API in `std::meta` + +Each of these are explained in more detail in the next sections but the wide picture is that +`comptime` allows us to write code which runs at compile-time. In this `comptime` code we +can quote and unquote snippets of the program, manipulate them, and insert them in other +parts of the program. Comptime functions which do this are said to be macros. Additionally, +there's a compile-time API of built-in types and functions provided by the compiler which allows +for greater analysis and modification of programs. + +--- + +## Comptime + +`comptime` is a new keyword in Noir which marks an item as executing or existing at compile-time. It can be used in several ways: + +- `comptime fn` to define functions which execute exclusively during compile-time. +- `comptime global` to define a global variable which is evaluated at compile-time. + - Unlike runtime globals, `comptime global`s can be mutable. +- `comptime { ... }` to execute a block of statements during compile-time. +- `comptime let` to define a variable whose value is evaluated at compile-time. +- `comptime for` to run a for loop at compile-time. Syntax sugar for `comptime { for .. }`. + +### Scoping + +Note that while in a `comptime` context, any runtime variables _local to the current function_ are never visible. + +### Evaluating + +Evaluation rules of `comptime` follows the normal unconstrained evaluation rules for other Noir code. There are a few things to note though: + +- Certain built-in functions may not be available, although more may be added over time. +- Evaluation order of global items is currently unspecified. For example, given the following two functions we can't guarantee +which `println` will execute first. The ordering of the two printouts will be arbitrary, but should be stable across multiple compilations with the same `nargo` version as long as the program is also unchanged. + +```rust +fn one() { + comptime { println("one"); } +} + +fn two() { + comptime { println("two"); } +} +``` + +- Since evaluation order is unspecified, care should be taken when using mutable globals so that they do not rely on a particular ordering. +For example, using globals to generate unique ids should be fine but relying on certain ids always being produced (especially after edits to the program) should be avoided. +- Although most ordering of globals is unspecified, two are: + - Dependencies of a crate will always be evaluated before the dependent crate. + - Any annotations on a function will be run before the function itself is resolved. This is to allow the annotation to modify the function if necessary. Note that if the + function itself was called at compile-time previously, it will already be resolved and cannot be modified. To prevent accidentally calling functions you wish to modify + at compile-time, it may be helpful to sort your `comptime` annotation functions into a different crate along with any dependencies they require. + +### Lowering + +When a `comptime` value is used in runtime code it must be lowered into a runtime value. This means replacing the expression with the literal that it evaluated to. For example, the code: + +```rust +struct Foo { array: [Field; 2], len: u32 } + +fn main() { + println(comptime { + let mut foo = std::mem::zeroed::(); + foo.array[0] = 4; + foo.len = 1; + foo + }); +} +``` + +will be converted to the following after `comptime` expressions are evaluated: + +```rust +struct Foo { array: [Field; 2], len: u32 } + +fn main() { + println(Foo { array: [4, 0], len: 1 }); +} +``` + +Not all types of values can be lowered. For example, `Type`s and `TypeDefinition`s (among other types) cannot be lowered at all. + +```rust +fn main() { + // There's nothing we could inline here to create a Type value at runtime + // let _ = get_type!(); +} + +comptime fn get_type() -> Type { ... } +``` + +--- + +## (Quasi) Quote + +Macros in Noir are `comptime` functions which return code as a value which is inserted into the call site when it is lowered there. +A code value in this case is of type `Quoted` and can be created by a `quote { ... }` expression. +More specifically, the code value `quote` creates is a token stream - a representation of source code as a series of words, numbers, string literals, or operators. +For example, the expression `quote { Hi "there reader"! }` would quote three tokens: the word "hi", the string "there reader", and an exclamation mark. +You'll note that snippets that would otherwise be invalid syntax can still be quoted. + +When a `Quoted` value is used in runtime code, it is lowered into a `quote { ... }` expression. Since this expression is only valid +in compile-time code however, we'd get an error if we tried this. Instead, we can use macro insertion to insert each token into the +program at that point, and parse it as an expression. To do this, we have to add a `!` after the function name returning the `Quoted` value. +If the value was created locally and there is no function returning it, `std::meta::unquote!(_)` can be used instead. +Calling such a function at compile-time without `!` will just return the `Quoted` value to be further manipulated. For example: + +```rust title="quote-example" showLineNumbers +comptime fn quote_one() -> Quoted { + quote { 1 } + } + + #[test] + fn returning_versus_macro_insertion() { + comptime { + // let _a: Quoted = quote { 1 }; + let _a: Quoted = quote_one(); + + // let _b: Field = 1; + let _b: Field = quote_one!(); + + // Since integers default to fields, if we + // want a different type we have to explicitly cast + // let _c: i32 = 1 as i32; + let _c: i32 = quote_one!() as i32; + } + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L120-L140 + + +For those familiar with quoting from other languages (primarily lisps), Noir's `quote` is actually a _quasiquote_. +This means we can escape the quoting by using the unquote operator to splice values in the middle of quoted code. + +## Unquote + +The unquote operator `$` is usable within a `quote` expression. +It takes a variable as an argument, evaluates the variable, and splices the resulting value into the quoted token stream at that point. For example, + +```rust +comptime { + let x = 1 + 2; + let y = quote { $x + 4 }; +} +``` + +The value of `y` above will be the token stream containing `3`, `+`, and `4`. We can also use this to combine `Quoted` values into larger token streams: + +```rust +comptime { + let x = quote { 1 + 2 }; + let y = quote { $x + 4 }; +} +``` + +The value of `y` above is now the token stream containing five tokens: `1 + 2 + 4`. + +Note that to unquote something, a variable name _must_ follow the `$` operator in a token stream. +If it is an expression (even a parenthesized one), it will do nothing. Most likely a parse error will be given when the macro is later unquoted. + +Unquoting can also be avoided by escaping the `$` with a backslash: + +``` +comptime { + let x = quote { 1 + 2 }; + + // y contains the four tokens: `$x + 4` + let y = quote { \$x + 4 }; +} +``` + +--- + +## Annotations + +Annotations provide a way to run a `comptime` function on an item in the program. +When you use an annotation, the function with the same name will be called with that item as an argument: + +```rust +#[my_struct_annotation] +struct Foo {} + +comptime fn my_struct_annotation(s: StructDefinition) { + println("Called my_struct_annotation!"); +} + +#[my_function_annotation] +fn foo() {} + +comptime fn my_function_annotation(f: FunctionDefinition) { + println("Called my_function_annotation!"); +} +``` + +Anything returned from one of these functions will be inserted at top-level along with the original item. +Note that expressions are not valid at top-level so you'll get an error trying to return `3` or similar just as if you tried to write a program containing `3; struct Foo {}`. +You can insert other top-level items such as trait impls, structs, or functions this way though. +For example, this is the mechanism used to insert additional trait implementations into the program when deriving a trait impl from a struct: + +```rust title="derive-field-count-example" showLineNumbers +trait FieldCount { + fn field_count() -> u32; + } + + #[derive_field_count] + struct Bar { + x: Field, + y: [Field; 2], + } + + comptime fn derive_field_count(s: StructDefinition) -> Quoted { + let typ = s.as_type(); + let field_count = s.fields().len(); + quote { + impl FieldCount for $typ { + fn field_count() -> u32 { + $field_count + } + } + } + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L142-L164 + + +### Calling annotations with additional arguments + +Arguments may optionally be given to annotations. +When this is done, these additional arguments are passed to the annotation function after the item argument. + +```rust title="annotation-arguments-example" showLineNumbers +#[assert_field_is_type(quote { i32 }.as_type())] + struct MyStruct { + my_field: i32, + } + + comptime fn assert_field_is_type(s: StructDefinition, typ: Type) { + // Assert the first field in `s` has type `typ` + let fields = s.fields(); + assert_eq(fields[0].1, typ); + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L166-L177 + + +We can also take any number of arguments by adding the `varargs` annotation: + +```rust title="annotation-varargs-example" showLineNumbers +#[assert_three_args(1, 2, 3)] + struct MyOtherStruct { + my_other_field: u32, + } + + #[varargs] + comptime fn assert_three_args(_s: StructDefinition, args: [Field]) { + assert_eq(args.len(), 3); + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L179-L189 + + +--- + +## Comptime API + +Although `comptime`, `quote`, and unquoting provide a flexible base for writing macros, +Noir's true metaprogramming ability comes from being able to interact with the compiler through a compile-time API. +This API can be accessed through built-in functions in `std::meta` as well as on methods of several `comptime` types. + +The following is an incomplete list of some `comptime` types along with some useful methods on them. You can see more in the standard library [Metaprogramming section](../standard_library/meta). + +- `Quoted`: A token stream +- `Type`: The type of a Noir type + - `fn implements(self, constraint: TraitConstraint) -> bool` + - Returns true if `self` implements the given trait constraint +- `Expr`: A syntactically valid expression. Can be used to recur on a program's parse tree to inspect how it is structured. + - Methods: + - `fn as_function_call(self) -> Option<(Expr, [Expr])>` + - If this is a function call expression, return `(function, arguments)` + - `fn as_block(self) -> Option<[Expr]>` + - If this is a block, return each statement in the block +- `FunctionDefinition`: A function definition + - Methods: + - `fn parameters(self) -> [(Quoted, Type)]` + - Returns a slice of `(name, type)` pairs for each parameter +- `StructDefinition`: A struct definition + - Methods: + - `fn as_type(self) -> Type` + - Returns this `StructDefinition` as a `Type`. Any generics are kept as-is + - `fn generics(self) -> [Quoted]` + - Return the name of each generic on this struct + - `fn fields(self) -> [(Quoted, Type)]` + - Return the name and type of each field +- `TraitConstraint`: A trait constraint such as `From` +- `TypedExpr`: A type-checked expression. +- `UnresolvedType`: A syntactic notation that refers to a Noir type that hasn't been resolved yet + +There are many more functions available by exploring the `std::meta` module and its submodules. +Using these methods is the key to writing powerful metaprogramming libraries. + +### `#[use_callers_scope]` + +Since certain functions such as `Quoted::as_type`, `Expression::as_type`, or `Quoted::as_trait_constraint` will attempt +to resolve their contents in a particular scope - it can be useful to change the scope they resolve in. By default +these functions will resolve in the current function's scope which is usually the attribute function they are called in. +If you're working on a library however, this may be a completely different module or crate to the item you're trying to +use the attribute on. If you want to be able to use `Quoted::as_type` to refer to types local to the caller's scope for +example, you can annotate your attribute function with `#[use_callers_scope]`. This will ensure your attribute, and any +closures it uses, can refer to anything in the caller's scope. `#[use_callers_scope]` also works recursively. So if both +your attribute function and a helper function it calls use it, then they can both refer to the same original caller. + +--- + +## Example: Derive + +Using all of the above, we can write a `derive` macro that behaves similarly to Rust's but is not built into the language. +From the user's perspective it will look like this: + +```rust +// Example usage +#[derive(Default, Eq, Ord)] +struct MyStruct { my_field: u32 } +``` + +To implement `derive` we'll have to create a `comptime` function that accepts +a variable amount of traits. + +```rust title="derive_example" showLineNumbers +// These are needed for the unconstrained hashmap we're using to store derive functions +use crate::collections::umap::UHashMap; +use crate::hash::BuildHasherDefault; +use crate::hash::poseidon2::Poseidon2Hasher; + +// A derive function is one that given a struct definition can +// create us a quoted trait impl from it. +pub type DeriveFunction = fn(StructDefinition) -> Quoted; + +// We'll keep a global HANDLERS map to keep track of the derive handler for each trait +comptime mut global HANDLERS: UHashMap> = + UHashMap::default(); + +// Given a struct and a slice of traits to derive, create trait impls for each. +// This function is as simple as iterating over the slice, checking if we have a trait +// handler registered for the given trait, calling it, and appending the result. +#[varargs] +pub comptime fn derive(s: StructDefinition, traits: [TraitDefinition]) -> Quoted { + let mut result = quote {}; + + for trait_to_derive in traits { + let handler = unsafe { HANDLERS.get(trait_to_derive) }; + assert(handler.is_some(), f"No derive function registered for `{trait_to_derive}`"); + + let trait_impl = handler.unwrap()(s); + result = quote { $result $trait_impl }; + } + + result +} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L31-L64 + + +Registering a derive function could be done as follows: + +```rust title="derive_via" showLineNumbers +// To register a handler for a trait, just add it to our handlers map +pub comptime fn derive_via(t: TraitDefinition, f: DeriveFunction) { + HANDLERS.insert(t, f); +} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L66-L73 + + +```rust title="big-derive-usage-example" showLineNumbers +// Finally, to register a handler we call the above function as an annotation + // with our handler function. + #[derive_via(derive_do_nothing)] + trait DoNothing { + fn do_nothing(self); + } + + comptime fn derive_do_nothing(s: StructDefinition) -> Quoted { + // This is simplified since we don't handle generics or where clauses! + // In a real example we'd likely also need to introduce each of + // `s.generics()` as well as a trait constraint for each generic + // to ensure they also implement the trait. + let typ = s.as_type(); + quote { + impl DoNothing for $typ { + fn do_nothing(self) { + // Traits can't tell us what to do + println("something"); + } + } + } + } + + // Since `DoNothing` is a simple trait which: + // 1. Only has one method + // 2. Does not have any generics on the trait itself + // We can use `std::meta::make_trait_impl` to help us out. + // This helper function will generate our impl for us along with any + // necessary where clauses and still provides a flexible interface + // for us to work on each field on the struct. + comptime fn derive_do_nothing_alt(s: StructDefinition) -> Quoted { + let trait_name = quote { DoNothing }; + let method_signature = quote { fn do_nothing(self) }; + + // Call `do_nothing` recursively on each field in the struct + let for_each_field = |field_name| quote { self.$field_name.do_nothing(); }; + + // Some traits like Eq want to join each field expression with something like `&`. + // We don't need that here + let join_fields_with = quote {}; + + // The body function is a spot to insert any extra setup/teardown needed. + // We'll insert our println here. Since we recur on each field, we should see + // one println for the struct itself, followed by a println for every field (recursively). + let body = |body| quote { + println("something"); + $body + }; + crate::meta::make_trait_impl( + s, + trait_name, + method_signature, + for_each_field, + join_fields_with, + body, + ) + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L191-L249 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/control_flow.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/control_flow.md new file mode 100644 index 00000000000..b365bb22728 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/control_flow.md @@ -0,0 +1,79 @@ +--- +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 +} +``` + +Alternatively, `start..=end` can be used for a range that is inclusive on both ends. + +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-v1.0.0-beta.0/noir/concepts/data_bus.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_bus.mdx new file mode 100644 index 00000000000..e55e58622ce --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_bus.mdx @@ -0,0 +1,23 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +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-v1.0.0-beta.0/noir/concepts/data_types/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..289145a8c4d --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,276 @@ +--- +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.mdx), 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. The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument. + +Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements. + +```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 the starting element. + +Requires `self` to be non-empty. + +```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); +} +``` + +### as_str_unchecked + +Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation - +the given array is interpreted as-is as a string. + +```rust +impl [u8; N] { + pub fn as_str_unchecked(self) -> str +} +``` + +example: + +```rust +fn main() { + let hi = [104, 105].as_str_unchecked(); + assert_eq(hi, "hi"); +} +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..2507af710e7 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,28 @@ +--- +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; +} +``` + +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.md) and +[Assert Function](../assert.md) sections. diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/fields.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..b9b56f7ecc3 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/fields.md @@ -0,0 +1,246 @@ +--- +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 title="to_le_bits" showLineNumbers +pub fn to_le_bits(self: Self) -> [u1; N] {} +``` +> Source code: noir_stdlib/src/field/mod.nr#L32-L34 + + +example: + +```rust title="to_le_bits_example" showLineNumbers +fn test_to_le_bits() { + let field = 2; + let bits: [u1; 8] = field.to_le_bits(); + assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L276-L282 + + + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust title="to_be_bits" showLineNumbers +pub fn to_be_bits(self: Self) -> [u1; N] {} +``` +> Source code: noir_stdlib/src/field/mod.nr#L48-L50 + + +example: + +```rust title="to_be_bits_example" showLineNumbers +fn test_to_be_bits() { + let field = 2; + let bits: [u1; 8] = field.to_be_bits(); + assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L267-L273 + + + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust title="to_le_bytes" showLineNumbers +pub fn to_le_bytes(self: Self) -> [u8; N] { +``` +> Source code: noir_stdlib/src/field/mod.nr#L61-L63 + + +example: + +```rust title="to_le_bytes_example" showLineNumbers +fn test_to_le_bytes() { + let field = 2; + let bytes: [u8; 8] = field.to_le_bytes(); + assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]); + assert_eq(Field::from_le_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L295-L302 + + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust title="to_be_bytes" showLineNumbers +pub fn to_be_bytes(self: Self) -> [u8; N] { +``` +> Source code: noir_stdlib/src/field/mod.nr#L94-L96 + + +example: + +```rust title="to_be_bytes_example" showLineNumbers +fn test_to_be_bytes() { + let field = 2; + let bytes: [u8; 8] = field.to_be_bytes(); + assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]); + assert_eq(Field::from_be_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L285-L292 + + + +### to_le_radix + +Decomposes into an array over the specified base, Little Endian + +```rust title="to_le_radix" showLineNumbers +pub fn to_le_radix(self: Self, radix: u32) -> [u8; N] { + // Brillig does not need an immediate radix + if !crate::runtime::is_unconstrained() { + crate::assert_constant(radix); + } + self.__to_le_radix(radix) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L118-L126 + + + +example: + +```rust title="to_le_radix_example" showLineNumbers +fn test_to_le_radix() { + let field = 2; + let bytes: [u8; 8] = field.to_le_radix(256); + assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]); + assert_eq(Field::from_le_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L315-L322 + + + +### to_be_radix + +Decomposes into an array over the specified base, Big Endian + +```rust title="to_be_radix" showLineNumbers +pub fn to_be_radix(self: Self, radix: u32) -> [u8; N] { + // Brillig does not need an immediate radix + if !crate::runtime::is_unconstrained() { + crate::assert_constant(radix); + } + self.__to_be_radix(radix) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L128-L136 + + +example: + +```rust title="to_be_radix_example" showLineNumbers +fn test_to_be_radix() { + let field = 2; + let bytes: [u8; 8] = field.to_be_radix(256); + assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]); + assert_eq(Field::from_be_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L305-L312 + + + +### 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 title="assert_max_bit_size" showLineNumbers +pub fn assert_max_bit_size(self) { +``` +> Source code: noir_stdlib/src/field/mod.nr#L10-L12 + + +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-v1.0.0-beta.0/noir/concepts/data_types/function_types.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..0f2db2b2d75 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/index.md @@ -0,0 +1,126 @@ +--- +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 +``` + +By default, like functions, type aliases are private to the module they exist in. You can use `pub` +to make the type alias public or `pub(crate)` to make it public to just its crate: + +```rust +// This type alias is now public +pub type Id = u8; +``` + +## Wildcard Type +Noir can usually infer the type of the variable from the context, so specifying the type of a variable is only required when it cannot be inferred. However, specifying a complex type can be tedious, especially when it has multiple generic arguments. Often some of the generic types can be inferred from the context, and Noir only needs a hint to properly infer the other types. We can partially specify a variable's type by using `_` as a marker, indicating where we still want the compiler to infer the type. + +```rust +let a: [_; 4] = foo(b); +``` + + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/integers.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..a1d59bf3166 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/integers.md @@ -0,0 +1,156 @@ +--- +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 execute +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 + +fn main(x: u8, y: u8) -> pub u8 { + std::wrapping_add(x, y) +} +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/references.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/data_types/slices.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..cfee564a302 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,358 @@ +--- +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 +fn main() -> pub u32 { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +To write a slice literal, use a preceding 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]); +} +``` + +### map + +Applies a function to each element of the slice, returning a new slice containing the mapped elements. + +```rust +fn map(self, f: fn[Env](T) -> U) -> [U] +``` + +example + +```rust +let a = &[1, 2, 3]; +let b = a.map(|a| a * 2); // b is now &[2, 4, 6] +``` + +### fold + +Applies a function to each element of the slice, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the slice, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = &[1]; +let a2 = &[1, 2]; +let a3 = &[1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let folded = slice.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as the starting element. + +```rust +fn reduce(self, f: fn[Env](T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let reduced = slice.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### filter + +Returns a new slice containing only elements for which the given predicate returns true. + +```rust +fn filter(self, f: fn[Env](T) -> bool) -> Self +``` + +example: + +```rust +fn main() { + let slice = &[1, 2, 3, 4, 5]; + let odds = slice.filter(|x| x % 2 == 1); + assert_eq(odds, &[1, 3, 5]); +} +``` + +### join + +Flatten each element in the slice into one value, separated by `separator`. + +Note that although slices implement `Append`, `join` cannot be used on slice +elements since nested slices are prohibited. + +```rust +fn join(self, separator: T) -> T where T: Append +``` + +example: + +```rust +struct Accumulator { + total: Field, +} + +// "Append" two accumulators by adding them +impl Append for Accumulator { + fn empty() -> Self { + Self { total: 0 } + } + + fn append(self, other: Self) -> Self { + Self { total: self.total + other.total } + } +} + +fn main() { + let slice = &[1, 2, 3, 4, 5].map(|total| Accumulator { total }); + + let result = slice.join(Accumulator::empty()); + assert_eq(result, Accumulator { total: 15 }); + + // We can use a non-empty separator to insert additional elements to sum: + let separator = Accumulator { total: 10 }; + let result = slice.join(separator); + assert_eq(result, Accumulator { total: 55 }); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(self, predicate: fn[Env](T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let all = slice.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 5]; + let any = slice.any(|a| a == 5); + assert(any); +} + +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..1fdee42425e --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/strings.md @@ -0,0 +1,79 @@ +--- +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.md). + +```rust + +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-v1.0.0-beta.0/noir/concepts/data_types/structs.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..29951ae843a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/structs.md @@ -0,0 +1,96 @@ +--- +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. + +### Visibility + +By default, like functions, structs are private to the module they exist in. You can use `pub` +to make the struct public or `pub(crate)` to make it public to just its crate: + +```rust +// This struct is now public +pub struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +The same applies to struct fields: by default they are private to the module they exist in, +but they can be made `pub` or `pub(crate)`: + +```rust +// This struct is now public +pub struct Animal { + hands: Field, // private to its module + pub(crate) legs: Field, // accessible from the entire crate + pub eyes: u8, // accessible from anywhere +} +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/tuples.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/functions.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/functions.md new file mode 100644 index 00000000000..f656cdfd97a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/generics.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/generics.md new file mode 100644 index 00000000000..c180a0ce7e6 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/generics.md @@ -0,0 +1,251 @@ +--- +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 +} +``` + +## Numeric Generics + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks similar to using regular generics, but introducing them into scope +requires declaring them with `let MyGenericName: IntegerType`. This can be done anywhere a normal +generic is declared. Instead of types, these generics resolve to integers at compile-time. +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 + } +} +``` + +## 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. + +## 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.md) 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.md). + +## Manually Specifying Generics with the Turbofish Operator + +There are times when the compiler cannot reasonably infer what type should be used for a generic, or when the developer themselves may want to manually distinguish generic type parameters. This is where the `::<>` turbofish operator comes into play. + +The `::<>` operator can follow a variable or path and can be used to manually specify generic arguments within the angle brackets. +The name "turbofish" comes from that `::<>` looks like a little fish. + +Examples: +```rust +fn main() { + let mut slice = []; + slice = slice.push_back(1); + slice = slice.push_back(2); + // Without turbofish a type annotation would be needed on the left hand side + let array = slice.as_array::<2>(); +} +``` + + +```rust +trait MyTrait { + fn ten() -> Self; +} + +impl MyTrait for Field { + fn ten() -> Self { 10 } +} + +struct Foo { + inner: T +} + +impl Foo { + fn generic_method(_self: Self) -> U where U: MyTrait { + U::ten() + } +} + +fn example() { + let foo: Foo = Foo { inner: 1 }; + // Using a type other than `Field` here (e.g. u32) would fail as + // there is no matching impl for `u32: MyTrait`. + // + // Substituting the `10` on the left hand side of this assert + // with `10 as u32` would also fail with a type mismatch as we + // are expecting a `Field` from the right hand side. + assert(10 as u32 == foo.generic_method::()); +} +``` + +## Arithmetic Generics + +In addition to numeric generics, Noir also allows a limited form of arithmetic on generics. +When you have a numeric generic such as `N`, you can use the following operators on it in a +type position: `+`, `-`, `*`, `/`, and `%`. + +Note that type checking arithmetic generics is a best effort guess from the compiler and there +are many cases of types that are equal that the compiler may not see as such. For example, +we know that `T * (N + M)` should be equal to `T*N + T*M` but the compiler does not currently +apply the distributive law and thus sees these as different types. + +Even with this limitation though, the compiler can handle common cases decently well: + +```rust +trait Serialize { + fn serialize(self) -> [Field; N]; +} + +impl Serialize<1> for Field { + fn serialize(self) -> [Field; 1] { + [self] + } +} + +impl Serialize for [T; N] + where T: Serialize { .. } + +impl Serialize for (T, U) + where T: Serialize, U: Serialize { .. } + +fn main() { + let data = (1, [2, 3, 4]); + assert_eq(data.serialize().len(), 4); +} +``` + +Note that if there is any over or underflow the types will fail to unify: + +```rust title="underflow-example" showLineNumbers +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn main() { + // error: Could not determine array length `(0 - 1)` + pop([]); +} +``` +> Source code: test_programs/compile_failure/arithmetic_generics_underflow/src/main.nr#L1-L14 + + +This also applies if there is underflow in an intermediate calculation: + +```rust title="intermediate-underflow-example" showLineNumbers +fn main() { + // From main it looks like there's nothing sketchy going on + seems_fine([]); +} + +// Since `seems_fine` says it can receive and return any length N +fn seems_fine(array: [Field; N]) -> [Field; N] { + // But inside `seems_fine` we pop from the array which + // requires the length to be greater than zero. + + // error: Could not determine array length `(0 - 1)` + push_zero(pop(array)) +} + +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn push_zero(array: [Field; N]) -> [Field; N + 1] { + let mut result: [Field; N + 1] = std::mem::zeroed(); + for i in 0..N { + result[i] = array[i]; + } + // index N is already zeroed + result +} +``` +> Source code: test_programs/compile_failure/arithmetic_generics_intermediate_underflow/src/main.nr#L1-L32 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/globals.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/globals.md new file mode 100644 index 00000000000..c64b6c53746 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/globals.md @@ -0,0 +1,82 @@ +--- +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 must be specified by the user: + +```rust +global N: Field = 5; + +global TUPLE: (Field, Field) = (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: u32 = 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: u32 = 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: Field = 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: [Field; 100] = 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. + +### Visibility + +By default, like functions, globals are private to the module they exist in. You can use `pub` +to make the global public or `pub(crate)` to make it public to just its crate: + +```rust +// This global is now public +pub global N: u32 = 5; +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/lambdas.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/mutability.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/ops.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/ops.md new file mode 100644 index 00000000000..c35c36c38a9 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/oracles.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/oracles.mdx new file mode 100644 index 00000000000..77a2ac1550a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/oracles.mdx @@ -0,0 +1,29 @@ +--- +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 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +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-v1.0.0-beta.0/noir/concepts/shadowing.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/concepts/traits.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/traits.md new file mode 100644 index 00000000000..b6c0a886eb0 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/traits.md @@ -0,0 +1,584 @@ +--- +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 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; let N: u32] 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 + } +} +``` + +Where clauses can also be placed on struct implementations. +For example, here is a method utilizing a generic type that implements the equality trait. + +```rust +struct Foo { + a: u32, + b: T, +} + +impl Foo where T: Eq { + fn eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.eq(other.b) + } +} +``` + +## 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); +} +``` + +### Associated Types and Constants + +Traits also support associated types and constraints which can be thought of as additional generics that are referred to by name. + +Here's an example of a trait with an associated type `Foo` and a constant `Bar`: + +```rust +trait MyTrait { + type Foo; + + let Bar: u32; +} +``` + +Now when we're implementing `MyTrait` we also have to provide values for `Foo` and `Bar`: + +```rust +impl MyTrait for Field { + type Foo = i32; + + let Bar: u32 = 11; +} +``` + +Since associated constants can also be used in a type position, its values are limited to only other +expression kinds allowed in numeric generics. + +Note that currently all associated types and constants must be explicitly specified in a trait constraint. +If we leave out any, we'll get an error that we're missing one: + +```rust +// Error! Constraint is missing associated constant for `Bar` +fn foo(x: T) where T: MyTrait { + ... +} +``` + +Because all associated types and constants must be explicitly specified, they are essentially named generics, +although this is set to change in the future. Future versions of Noir will allow users to elide associated types +in trait constraints similar to Rust. When this is done, you may still refer to their value with the `::AssociatedType` +syntax: + +```rust +// Only valid in future versions of Noir: +fn foo(x: T) where T: MyTrait { + let _: ::Foo = ...; +} +``` + +The type as trait syntax is possible in Noir today but is less useful when each type must be explicitly specified anyway: + +```rust +fn foo(x: T) where T: MyTrait { + // Works, but could just use F directly + let _: >::Foo = ...; + + let _: F = ...; +} +``` + +## 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: some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: 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. + +### Trait Inheritance + +Sometimes, you might need one trait to use another trait’s functionality (like "inheritance" in some other languages). In this case, you can specify this relationship by listing any child traits after the parent trait's name and a colon. Now, whenever the parent trait is implemented it will require the child traits to be implemented as well. A parent trait is also called a "super trait." + +```rust +trait Person { + fn name(self) -> String; +} + +// Person is a supertrait of Student. +// Implementing Student requires you to also impl Person. +trait Student: Person { + fn university(self) -> String; +} + +trait Programmer { + fn fav_language(self) -> String; +} + +// CompSciStudent (computer science student) is a subtrait of both Programmer +// and Student. Implementing CompSciStudent requires you to impl both supertraits. +trait CompSciStudent: Programmer + Student { + fn git_username(self) -> String; +} +``` + +### Trait Aliases + +Similar to the proposed Rust feature for [trait aliases](https://github.com/rust-lang/rust/blob/4d215e2426d52ca8d1af166d5f6b5e172afbff67/src/doc/unstable-book/src/language-features/trait-alias.md), +Noir supports aliasing one or more traits and using those aliases wherever +traits would normally be used. + +```rust +trait Foo { + fn foo(self) -> Self; +} + +trait Bar { + fn bar(self) -> Self; +} + +// Equivalent to: +// trait Baz: Foo + Bar {} +// +// impl Baz for T where T: Foo + Bar {} +trait Baz = Foo + Bar; + +// We can use `Baz` to refer to `Foo + Bar` +fn baz(x: T) -> T where T: Baz { + x.foo().bar() +} +``` + +#### Generic Trait Aliases + +Trait aliases can also be generic by placing the generic arguments after the +trait name. These generics are in scope of every item within the trait alias. + +```rust +trait Foo { + fn foo(self) -> Self; +} + +trait Bar { + fn bar(self) -> T; +} + +// Equivalent to: +// trait Baz: Foo + Bar {} +// +// impl Baz for U where U: Foo + Bar {} +trait Baz = Foo + Bar; +``` + +#### Trait Alias Where Clauses + +Trait aliases support where clauses to add trait constraints to any of their +generic arguments, e.g. ensuring `T: Baz` for a trait alias `Qux`. + +```rust +trait Foo { + fn foo(self) -> Self; +} + +trait Bar { + fn bar(self) -> T; +} + +trait Baz { + fn baz(self) -> bool; +} + +// Equivalent to: +// trait Qux: Foo + Bar where T: Baz {} +// +// impl Qux for U where +// U: Foo + Bar, +// T: Baz, +// {} +trait Qux = Foo + Bar where T: Baz; +``` + +Note that while trait aliases support where clauses, +the equivalent traits can fail due to [#6467](https://github.com/noir-lang/noir/issues/6467) + +### Visibility + +By default, like functions, traits and trait aliases are private to the module +they exist in. You can use `pub` to make the trait public or `pub(crate)` to make +it public to just its crate: + +```rust +// This trait is now public +pub trait Trait {} + +// This trait alias is now public +pub trait Baz = Foo + Bar; +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..b5221b8d2dd --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/concepts/unconstrained.md @@ -0,0 +1,104 @@ +--- +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 = unsafe { + 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). + +Note that in order to invoke unconstrained functions we need to wrap them in an `unsafe` block, +to make it clear that the call is unconstrained. + +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.md#break-and-continue) diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..24e02de08fe --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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 ecrecover; +use lib_a; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use std::hash::sha256; +use std::scalar_mul::fixed_base_embedded_curve; +``` + +Lastly, as demonstrated in the +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you +can import multiple items in the same line by enclosing them in curly braces: + +```rust +use std::ec::tecurve::affine::{Curve, Point}; +``` + +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) 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 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-v1.0.0-beta.0/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..14aa1f0579a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,221 @@ +--- +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 + +``` + +The module filename may also be the name of the module as a directory with the contents in a +file named `mod.nr` within that directory. The above example can alternatively be expressed like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +fn from_foo() {} +``` + +Note that it's an error to have both files `src/foo.nr` and `src/foo/mod.nr` in the filesystem. + +### 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 +``` + +Similar to importing a module in the crate root, modules can be placed in a `mod.nr` file, like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar/mod.nr` + +```rust +fn from_bar() {} +``` + +### Referencing a parent module + +Given a submodule, you can refer to its parent module using the `super` keyword. + +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 +// Same as bar::from_foo +use super::from_foo; + +fn from_bar() { + from_foo(); // invokes super::from_foo(), which is bar::from_foo() + super::from_foo(); // also invokes bar::from_foo() +} +``` + +### `use` visibility + +`use` declarations are private to the containing module, by default. However, like functions, +they can be marked as `pub` or `pub(crate)`. Such a use declaration serves to _re-export_ a name. +A public `use` declaration can therefore redirect some public name to a different target definition: +even a definition with a private canonical path, inside a different module. + +An example of re-exporting: + +```rust +mod some_module { + pub use foo::{bar, baz}; + mod foo { + pub fn bar() {} + pub fn baz() {} + } +} + +fn main() { + some_module::bar(); + some_module::baz(); +} +``` + +In this example, the module `some_module` re-exports two public names defined in `foo`. + +### Visibility + +By default, like functions, modules are private to the module (or crate) they exist in. You can use `pub` +to make the module public or `pub(crate)` to make it public to just its crate: + +```rust +// This module is now public and can be seen by other crates. +pub mod foo; +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..513497f12bf --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/standard_library/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/standard_library/bigint.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/bigint.md new file mode 100644 index 00000000000..05c3011634f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/bigint.md @@ -0,0 +1,127 @@ +--- +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. + +:::note + +`nargo` can be built with `--profile release-pedantic` to enable extra overflow checks which may affect `BigInt` results in some cases. +Consider the [`noir-bignum`](https://github.com/noir-lang/noir-bignum) library for an optimized alternative approach. + +::: + +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 +pub struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L28-L33 + + +## 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#L74-L82 + + +## 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-v1.0.0-beta.0/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..d6079ab182c --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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.mdx) + +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-v1.0.0-beta.0/noir/standard_library/bn254.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/standard_library/containers/boundedvec.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..509b214bf3a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,419 @@ +--- +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 good() -> 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 `good`'s return value + v2 +} + +fn bad() { + // Error: Type annotation needed + // The compiler can't infer `MaxLen` from this code. + let mut v3 = BoundedVec::new(); + 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(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(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 + + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to 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); + assert(first != 42); + v.set(0, 42); + let new_first = v.get(0); + assert(new_first == 42); +} +``` + +### set_unchecked + +```rust +pub fn set_unchecked(&mut self: Self, index: u64, value: T) -> T { +``` + +Writes an element to 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="set_unchecked_example" showLineNumbers +fn set_unchecked_example() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2]); + + // Here we're safely writing within the valid range of `vec` + // `vec` now has the value [42, 2] + vec.set_unchecked(0, 42); + + // We can then safely read this value back out of `vec`. + // Notice that we use the checked version of `get` which would prevent reading unsafe values. + assert_eq(vec.get(0), 42); + + // We've now written past the end of `vec`. + // As this index is still within the maximum potential length of `v`, + // it won't cause a constraint failure. + vec.set_unchecked(2, 42); + println(vec); + + // This will write past the end of the maximum potential length of `vec`, + // it will then trigger a constraint failure. + vec.set_unchecked(5, 42); + println(vec); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L67-L91 + + + +### 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#L95-L103 + + +### 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#L108-L120 + + +### 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#L125-L140 + + +### 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#L145-L151 + + +### 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#L156-L163 + + +### 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#L168-L175 + + +### 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#L180-L189 + + +### 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]) +``` + +### map + +```rust +pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec +``` + +Creates a new vector of equal size by calling a closure on each element in this vector. + +Example: + +```rust title="bounded-vec-map-example" showLineNumbers +let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| value * 2); +``` +> Source code: noir_stdlib/src/collections/bounded_vec.nr#L495-L498 + + +### 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#L256-L262 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/containers/hashmap.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..395cc312705 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,587 @@ +--- +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`. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a poseidon2 hasher +use 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, +{ + /// Constructs an empty HashMap. + /// + /// Example: + /// + /// ```noir + /// let hashmap: HashMap> = HashMap::default(); + /// assert(hashmap.is_empty()); + /// ``` + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L681-L696 + + +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#L207-L210 + + +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#L201-L203 + + +### 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#L103-L108 + + +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#L211-L216 + + +### 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#L465-L472 + + +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#L296-L304 + + +### 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#L507-L514 + + +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#L217-L221 + + +### 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#L563-L570 + + +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#L224-L231 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L167-L169 + + +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#L232-L240 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L424-L426 + + +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#L241-L256 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L446-L448 + + +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-L262 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +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#L143-L150 + + +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#L268-L275 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L191-L193 + + +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#L307-L318 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L227-L229 + + +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#L319-L329 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L262-L264 + + +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#L330-L339 + + +### 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#L297-L304 + + +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#L343-L346 + + +### 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#L335-L342 + + +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#L347-L350 + + +### 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#L367-L369 + + +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#L351-L354 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L388-L390 + + +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#L279-L281 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default, +{ + /// Constructs an empty HashMap. + /// + /// Example: + /// + /// ```noir + /// let hashmap: HashMap> = HashMap::default(); + /// assert(hashmap.is_empty()); + /// ``` + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L681-L696 + + +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#L207-L210 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher, +{ + /// Checks if two HashMaps are equal. + /// + /// Example: + /// + /// ```noir + /// 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); + /// ``` + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L629-L654 + + +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#L282-L293 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/containers/index.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/standard_library/containers/vec.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..475011922f8 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,170 @@ +--- +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); +``` + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +Panics if the index points beyond the vector's end. + +Example: + +```rust +let vector: Vec = Vec::from_slice(&[10, 20, 30]); +assert(vector.get(1) == 20); +vector.set(1, 42); +assert(vector.get(1) == 42); +``` + +### 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-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/ciphers.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/ciphers.mdx new file mode 100644 index 00000000000..d6a5e1a79eb --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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'; + +## 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-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..00b8071487e --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,101 @@ +--- +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/mod.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec/mod.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/mod.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 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 the [eddsa](https://github.com/noir-lang/eddsa) library an example of eddsa signature verification + over the Baby Jubjub curve. diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..8d96027b42c --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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'; + +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-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx new file mode 100644 index 00000000000..482a36932b9 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx @@ -0,0 +1,95 @@ +--- +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'; + +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: [EmbeddedCurvePoint; N], + scalars: [EmbeddedCurveScalar; N], +) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L103-L108 + + +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: EmbeddedCurveScalar) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L120-L122 + + +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 +pub fn embedded_curve_add( + point1: EmbeddedCurvePoint, + point2: EmbeddedCurvePoint, +) -> EmbeddedCurvePoint { +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L136-L141 + + +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-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..541a1971561 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,227 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s and pedersen +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox'; + +## 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]) -> HASH +``` +> Source code: noir_stdlib/src/hash/sha256.nr#L47-L49 + + +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#L15-L17 + + +```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/mod.nr#L18-L20 + + +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/mod.nr#L24-L26 + + +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/mod.nr#L49-L51 + + +example: + +```rust title="pedersen-hash" showLineNumbers +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-L6 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { +``` +> Source code: noir_stdlib/src/hash/mod.nr#L29-L31 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +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); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L7 + + + + +## 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/mod.nr#L116-L118 + + +example: + +```rust title="keccak256" showLineNumbers +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-L20 + + + + +## 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 std::hash::poseidon; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L11 + + +## 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); +``` + +example: + +```rust title="poseidon2" showLineNumbers +use std::hash::poseidon2; + +fn main(inputs: [Field; 4], expected_hash: Field) { + let hash = poseidon2::Poseidon2::hash(inputs, inputs.len()); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/poseidon2/src/main.nr#L1-L8 + + +## 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-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..030452645c5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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'; + +## 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#L4-L11 + + +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#L15-L22 + + + diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/fmtstr.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/fmtstr.md new file mode 100644 index 00000000000..19809d60261 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/fmtstr.md @@ -0,0 +1,17 @@ +--- +title: fmtstr +--- + +`fmtstr` is the type resulting from using format string (`f"..."`). + +## Methods + +### quoted_contents + +```rust title="quoted_contents" showLineNumbers +pub comptime fn quoted_contents(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/format_string.nr#L3-L5 + + +Returns the format string contents (that is, without the leading and trailing double quotes) as a `Quoted` value. \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/is_unconstrained.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/is_unconstrained.md new file mode 100644 index 00000000000..51bb1bda8f1 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/is_unconstrained.md @@ -0,0 +1,69 @@ +--- +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. + +Note that using `is_unconstrained` in a `comptime` context will also return `true`: + +``` +fn main() { + comptime { + assert(is_unconstrained()); + } +} +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/logging.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/standard_library/mem.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/mem.md new file mode 100644 index 00000000000..3619550273e --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/mem.md @@ -0,0 +1,82 @@ +--- +title: Memory Module +description: + This module contains functions which manipulate memory in a low-level way +keywords: + [ + mem, memory, zeroed, transmute, checked_transmute + ] +--- + +# `std::mem::zeroed` + +```rust +fn zeroed() -> T +``` + +Returns 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. + +This function currently supports the following types: + +- Field +- Bool +- Uint +- Array +- Slice +- String +- Tuple +- Functions + +Using it on other types could result in unexpected behavior. + +# `std::mem::checked_transmute` + +```rust +fn checked_transmute(value: T) -> U +``` + +Transmutes a value of one type into the same value but with a new type `U`. + +This function is safe to use since both types are asserted to be equal later during compilation after the concrete values for generic types become known. +This function is useful for cases where the compiler may fails a type check that is expected to pass where +a user knows the two types to be equal. For example, when using arithmetic generics there are cases the compiler +does not see as equal, such as `[Field; N*(A + B)]` and `[Field; N*A + N*B]`, which users may know to be equal. +In these cases, `checked_transmute` can be used to cast the value to the desired type while also preserving safety +by checking this equality once `N`, `A`, `B` are fully resolved. + +Note that since this safety check is performed after type checking rather than during, no error is issued if the function +containing `checked_transmute` is never called. + +# `std::mem::array_refcount` + +```rust +fn array_refcount(array: [T; N]) -> u32 {} +``` + +Returns the internal reference count of an array value in unconstrained code. + +Arrays only have reference count in unconstrained code - using this anywhere +else will return zero. + +This function is mostly intended for debugging compiler optimizations but can also be used +to find where array copies may be happening in unconstrained code by placing it before array +mutations. + +# `std::mem::slice_refcount` + +```rust +fn slice_refcount(slice: [T]) -> u32 {} +``` + +Returns the internal reference count of a slice value in unconstrained code. + +Slices only have reference count in unconstrained code - using this anywhere +else will return zero. + +This function is mostly intended for debugging compiler optimizations but can also be used +to find where slice copies may be happening in unconstrained code by placing it before slice +mutations. diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..6a9ebf72ada --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/standard_library/meta/ctstring.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/ctstring.md new file mode 100644 index 00000000000..b76f873ca03 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/ctstring.md @@ -0,0 +1,100 @@ +--- +title: CtString +--- + +`std::meta::ctstring` contains methods on the built-in `CtString` type which is +a compile-time, dynamically-sized string type. Compared to `str` and `fmtstr`, +`CtString` is useful because its size does not need to be specified in its type. This +can be used for formatting items at compile-time or general string handling in `comptime` +code. + +Since `fmtstr`s can be converted into `CtString`s, you can make use of their formatting +abilities in CtStrings by formatting in `fmtstr`s then converting the result to a CtString +afterward. + +## Traits + +### AsCtString + +```rust title="as-ctstring" showLineNumbers +pub trait AsCtString { + comptime fn as_ctstring(self) -> CtString; +} +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L43-L47 + + +Converts an object into a compile-time string. + +Implementations: + +```rust +impl AsCtString for str { ... } +impl AsCtString for fmtstr { ... } +``` + +## Methods + +### new + +```rust title="new" showLineNumbers +pub comptime fn new() -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L4-L6 + + +Creates an empty `CtString`. + +### append_str + +```rust title="append_str" showLineNumbers +pub comptime fn append_str(self, s: str) -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L11-L13 + + +Returns a new CtString with the given str appended onto the end. + +### append_fmtstr + +```rust title="append_fmtstr" showLineNumbers +pub comptime fn append_fmtstr(self, s: fmtstr) -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L17-L19 + + +Returns a new CtString with the given fmtstr appended onto the end. + +### as_quoted_str + +```rust title="as_quoted_str" showLineNumbers +pub comptime fn as_quoted_str(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L26-L28 + + +Returns a quoted string literal from this string's contents. + +There is no direct conversion from a `CtString` to a `str` since +the size would not be known. To get around this, this function can +be used in combination with macro insertion (`!`) to insert this string +literal at this function's call site. + +Example: + +```rust title="as_quoted_str_example" showLineNumbers +let my_ctstring = "foo bar".as_ctstring(); + let my_str = my_ctstring.as_quoted_str!(); + + assert_eq(crate::meta::type_of(my_str), quote { str<7> }.as_type()); +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L92-L97 + + +## Trait Implementations + +```rust +impl Eq for CtString +impl Hash for CtString +impl Append for CtString +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/expr.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/expr.md new file mode 100644 index 00000000000..b6d395c6700 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/expr.md @@ -0,0 +1,380 @@ +--- +title: Expr +--- + +`std::meta::expr` contains methods on the built-in `Expr` type for quoted, syntactically valid expressions. + +## Methods + +### as_array + +```rust title="as_array" showLineNumbers +pub comptime fn as_array(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L10-L12 + + +If this expression is an array, this returns a slice of each element in the array. + +### as_assert + +```rust title="as_assert" showLineNumbers +pub comptime fn as_assert(self) -> Option<(Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L16-L18 + + +If this expression is an assert, this returns the assert expression and the optional message. + +### as_assert_eq + +```rust title="as_assert_eq" showLineNumbers +pub comptime fn as_assert_eq(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L23-L25 + + +If this expression is an assert_eq, this returns the left-hand-side and right-hand-side +expressions, together with the optional message. + +### as_assign + +```rust title="as_assign" showLineNumbers +pub comptime fn as_assign(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L30-L32 + + +If this expression is an assignment, this returns a tuple with the left hand side +and right hand side in order. + +### as_binary_op + +```rust title="as_binary_op" showLineNumbers +pub comptime fn as_binary_op(self) -> Option<(Expr, BinaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L37-L39 + + +If this expression is a binary operator operation ` `, +return the left-hand side, operator, and the right-hand side of the operation. + +### as_block + +```rust title="as_block" showLineNumbers +pub comptime fn as_block(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L44-L46 + + +If this expression is a block `{ stmt1; stmt2; ...; stmtN }`, return +a slice containing each statement. + +### as_bool + +```rust title="as_bool" showLineNumbers +pub comptime fn as_bool(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L50-L52 + + +If this expression is a boolean literal, return that literal. + +### as_cast + +```rust title="as_cast" showLineNumbers +#[builtin(expr_as_cast)] + pub comptime fn as_cast(self) -> Option<(Expr, UnresolvedType)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L56-L59 + + +If this expression is a cast expression (`expr as type`), returns the casted +expression and the type to cast to. + +### as_comptime + +```rust title="as_comptime" showLineNumbers +pub comptime fn as_comptime(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L64-L66 + + +If this expression is a `comptime { stmt1; stmt2; ...; stmtN }` block, +return each statement in the block. + +### as_constructor + +```rust title="as_constructor" showLineNumbers +pub comptime fn as_constructor(self) -> Option<(UnresolvedType, [(Quoted, Expr)])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L71-L73 + + +If this expression is a constructor `Type { field1: expr1, ..., fieldN: exprN }`, +return the type and the fields. + +### as_for + +```rust title="as_for" showLineNumbers +pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L78-L80 + + +If this expression is a for statement over a single expression, return the identifier, +the expression and the for loop body. + +### as_for_range + +```rust title="as_for" showLineNumbers +pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L78-L80 + + +If this expression is a for statement over a range, return the identifier, +the range start, the range end and the for loop body. + +### as_function_call + +```rust title="as_function_call" showLineNumbers +pub comptime fn as_function_call(self) -> Option<(Expr, [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L92-L94 + + +If this expression is a function call `foo(arg1, ..., argN)`, return +the function and a slice of each argument. + +### as_if + +```rust title="as_if" showLineNumbers +pub comptime fn as_if(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L100-L102 + + +If this expression is an `if condition { then_branch } else { else_branch }`, +return the condition, then branch, and else branch. If there is no else branch, +`None` is returned for that branch instead. + +### as_index + +```rust title="as_index" showLineNumbers +pub comptime fn as_index(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L107-L109 + + +If this expression is an index into an array `array[index]`, return the +array and the index. + +### as_integer + +```rust title="as_integer" showLineNumbers +pub comptime fn as_integer(self) -> Option<(Field, bool)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L114-L116 + + +If this expression is an integer literal, return the integer as a field +as well as whether the integer is negative (true) or not (false). + +### as_lambda + +```rust title="as_lambda" showLineNumbers +pub comptime fn as_lambda( + self, + ) -> Option<([(Expr, Option)], Option, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L120-L124 + + +If this expression is a lambda, returns the parameters, return type and body. + +### as_let + +```rust title="as_let" showLineNumbers +pub comptime fn as_let(self) -> Option<(Expr, Option, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L129-L131 + + +If this expression is a let statement, returns the let pattern as an `Expr`, +the optional type annotation, and the assigned expression. + +### as_member_access + +```rust title="as_member_access" showLineNumbers +pub comptime fn as_member_access(self) -> Option<(Expr, Quoted)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L136-L138 + + +If this expression is a member access `foo.bar`, return the struct/tuple +expression and the field. The field will be represented as a quoted value. + +### as_method_call + +```rust title="as_method_call" showLineNumbers +pub comptime fn as_method_call(self) -> Option<(Expr, Quoted, [UnresolvedType], [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L143-L145 + + +If this expression is a method call `foo.bar::(arg1, ..., argN)`, return +the receiver, method name, a slice of each generic argument, and a slice of each argument. + +### as_repeated_element_array + +```rust title="as_repeated_element_array" showLineNumbers +pub comptime fn as_repeated_element_array(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L150-L152 + + +If this expression is a repeated element array `[elem; length]`, return +the repeated element and the length expressions. + +### as_repeated_element_slice + +```rust title="as_repeated_element_slice" showLineNumbers +pub comptime fn as_repeated_element_slice(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L157-L159 + + +If this expression is a repeated element slice `[elem; length]`, return +the repeated element and the length expressions. + +### as_slice + +```rust title="as_slice" showLineNumbers +pub comptime fn as_slice(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L164-L166 + + +If this expression is a slice literal `&[elem1, ..., elemN]`, +return each element of the slice. + +### as_tuple + +```rust title="as_tuple" showLineNumbers +pub comptime fn as_tuple(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L171-L173 + + +If this expression is a tuple `(field1, ..., fieldN)`, +return each element of the tuple. + +### as_unary_op + +```rust title="as_unary_op" showLineNumbers +pub comptime fn as_unary_op(self) -> Option<(UnaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L178-L180 + + +If this expression is a unary operation ` `, +return the unary operator as well as the right-hand side expression. + +### as_unsafe + +```rust title="as_unsafe" showLineNumbers +pub comptime fn as_unsafe(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L185-L187 + + +If this expression is an `unsafe { stmt1; ...; stmtN }` block, +return each statement inside in a slice. + +### has_semicolon + +```rust title="has_semicolon" showLineNumbers +pub comptime fn has_semicolon(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L206-L208 + + +`true` if this expression is trailed by a semicolon. E.g. + +``` +comptime { + let expr1 = quote { 1 + 2 }.as_expr().unwrap(); + let expr2 = quote { 1 + 2; }.as_expr().unwrap(); + + assert(expr1.as_binary_op().is_some()); + assert(expr2.as_binary_op().is_some()); + + assert(!expr1.has_semicolon()); + assert(expr2.has_semicolon()); +} +``` + +### is_break + +```rust title="is_break" showLineNumbers +pub comptime fn is_break(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L212-L214 + + +`true` if this expression is `break`. + +### is_continue + +```rust title="is_continue" showLineNumbers +pub comptime fn is_continue(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L218-L220 + + +`true` if this expression is `continue`. + +### modify + +```rust title="modify" showLineNumbers +pub comptime fn modify(self, f: fn[Env](Expr) -> Option) -> Expr { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L229-L231 + + +Applies a mapping function to this expression and to all of its sub-expressions. +`f` will be applied to each sub-expression first, then applied to the expression itself. + +This happens recursively for every expression within `self`. + +For example, calling `modify` on `(&[1], &[2, 3])` with an `f` that returns `Option::some` +for expressions that are integers, doubling them, would return `(&[2], &[4, 6])`. + +### quoted + +```rust title="quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L266-L268 + + +Returns this expression as a `Quoted` value. It's the same as `quote { $self }`. + +### resolve + +```rust title="resolve" showLineNumbers +pub comptime fn resolve(self, in_function: Option) -> TypedExpr {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L282-L284 + + +Resolves and type-checks this expression and returns the result as a `TypedExpr`. + +The `in_function` argument specifies where the expression is resolved: +- If it's `none`, the expression is resolved in the function where `resolve` was called +- If it's `some`, the expression is resolved in the given function + +If any names used by this expression are not in scope or if there are any type errors, +this will give compiler errors as if the expression was written directly into +the current `comptime` function. \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/function_def.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/function_def.md new file mode 100644 index 00000000000..b7f2ebdb889 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/function_def.md @@ -0,0 +1,166 @@ +--- +title: FunctionDefinition +--- + +`std::meta::function_def` contains methods on the built-in `FunctionDefinition` type representing +a function definition in the source program. + +## Methods + +### add_attribute + +```rust title="add_attribute" showLineNumbers +pub comptime fn add_attribute(self, attribute: str) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L3-L5 + + +Adds an attribute to the function. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### body + +```rust title="body" showLineNumbers +pub comptime fn body(self) -> Expr {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L8-L10 + + +Returns the body of the function as an expression. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +pub comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L13-L15 + + +Returns true if this function has a custom attribute with the given name. + +### is_unconstrained + +```rust title="is_unconstrained" showLineNumbers +pub comptime fn is_unconstrained(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L18-L20 + + +Returns true if this function is unconstrained. + +### module + +```rust title="module" showLineNumbers +pub comptime fn module(self) -> Module {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L23-L25 + + +Returns the module where the function is defined. + +### name + +```rust title="name" showLineNumbers +pub comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L28-L30 + + +Returns the name of the function. + +### parameters + +```rust title="parameters" showLineNumbers +pub comptime fn parameters(self) -> [(Quoted, Type)] {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L33-L35 + + +Returns each parameter of the function as a tuple of (parameter pattern, parameter type). + +### return_type + +```rust title="return_type" showLineNumbers +pub comptime fn return_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L38-L40 + + +The return type of the function. + +### set_body + +```rust title="set_body" showLineNumbers +pub comptime fn set_body(self, body: Expr) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L43-L45 + + +Mutate the function body to a new expression. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_parameters + +```rust title="set_parameters" showLineNumbers +pub comptime fn set_parameters(self, parameters: [(Quoted, Type)]) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L48-L50 + + +Mutates the function's parameters to a new set of parameters. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +Expects a slice of (parameter pattern, parameter type) for each parameter. Requires +each parameter pattern to be a syntactically valid parameter. + +### set_return_type + +```rust title="set_return_type" showLineNumbers +pub comptime fn set_return_type(self, return_type: Type) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L53-L55 + + +Mutates the function's return type to a new type. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_return_public + +```rust title="set_return_public" showLineNumbers +pub comptime fn set_return_public(self, public: bool) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L58-L60 + + +Mutates the function's return visibility to public (if `true` is given) or private (if `false` is given). +This is only valid on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_unconstrained + +```rust title="set_unconstrained" showLineNumbers +pub comptime fn set_unconstrained(self, value: bool) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L66-L68 + + +Mutates the function to be unconstrained (if `true` is given) or not (if `false` is given). +This is only valid on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +## Trait Implementations + +```rust +impl Eq for FunctionDefinition +impl Hash for FunctionDefinition +``` + +Note that each function is assigned a unique ID internally and this is what is used for +equality and hashing. So even functions with identical signatures and bodies may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/index.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/index.md new file mode 100644 index 00000000000..14544c07442 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/index.md @@ -0,0 +1,224 @@ +--- +title: Metaprogramming +description: Noir's Metaprogramming API +keywords: [metaprogramming, comptime, macros, macro, quote, unquote] +--- + +`std::meta` is the entry point for Noir's metaprogramming API. This consists of `comptime` functions +and types used for inspecting and modifying Noir programs. + +## Functions + +### type_of + +```rust title="type_of" showLineNumbers +pub comptime fn type_of(x: T) -> Type {} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L27-L29 + + +Returns the type of a variable at compile-time. + +Example: +```rust +comptime { + let x: i32 = 1; + let x_type: Type = std::meta::type_of(x); + + assert_eq(x_type, quote { i32 }.as_type()); +} +``` + +### unquote + +```rust title="unquote" showLineNumbers +pub comptime fn unquote(code: Quoted) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L19-L21 + + +Unquotes the passed-in token stream where this function was called. + +Example: +```rust +comptime { + let code = quote { 1 + 2 }; + + // let x = 1 + 2; + let x = unquote!(code); +} +``` + +### derive + +```rust title="derive" showLineNumbers +#[varargs] +pub comptime fn derive(s: StructDefinition, traits: [TraitDefinition]) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L48-L51 + + +Attribute placed on struct definitions. + +Creates a trait impl for each trait passed in as an argument. +To do this, the trait must have a derive handler registered +with `derive_via` beforehand. The traits in the stdlib that +can be derived this way are `Eq`, `Ord`, `Default`, and `Hash`. + +Example: +```rust +#[derive(Eq, Default)] +struct Foo { + x: i32, + y: T, +} + +fn main() { + let foo1 = Foo::default(); + let foo2 = Foo { x: 0, y: &[0] }; + assert_eq(foo1, foo2); +} +``` + +### derive_via + +```rust title="derive_via_signature" showLineNumbers +pub comptime fn derive_via(t: TraitDefinition, f: DeriveFunction) { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L68-L70 + + +Attribute placed on trait definitions. + +Registers a function to create impls for the given trait +when the trait is used in a `derive` call. Users may use +this to register their own functions to enable their traits +to be derived by `derive`. + +Because this function requires a function as an argument which +should produce a trait impl for any given struct, users may find +it helpful to use a function like `std::meta::make_trait_impl` to +help creating these impls. + +Example: +```rust +#[derive_via(derive_do_nothing)] +trait DoNothing { + fn do_nothing(self); +} + +comptime fn derive_do_nothing(s: StructDefinition) -> Quoted { + let typ = s.as_type(); + quote { + impl DoNothing for $typ { + fn do_nothing(self) { + println("Nothing"); + } + } + } +} +``` + +As another example, `derive_eq` in the stdlib is used to derive the `Eq` +trait for any struct. It makes use of `make_trait_impl` to do this: + +```rust title="derive_eq" showLineNumbers +comptime fn derive_eq(s: StructDefinition) -> Quoted { + let signature = quote { fn eq(_self: Self, _other: Self) -> bool }; + let for_each_field = |name| quote { (_self.$name == _other.$name) }; + let body = |fields| { + if s.fields().len() == 0 { + quote { true } + } else { + fields + } + }; + crate::meta::make_trait_impl( + s, + quote { Eq }, + signature, + for_each_field, + quote { & }, + body, + ) +} +``` +> Source code: noir_stdlib/src/cmp.nr#L10-L30 + + +### make_trait_impl + +```rust title="make_trait_impl" showLineNumbers +pub comptime fn make_trait_impl( + s: StructDefinition, + trait_name: Quoted, + function_signature: Quoted, + for_each_field: fn[Env1](Quoted) -> Quoted, + join_fields_with: Quoted, + body: fn[Env2](Quoted) -> Quoted, +) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L87-L96 + + +A helper function to more easily create trait impls while deriving traits. + +Note that this function only works for traits which: +1. Have only one method +2. Have no generics on the trait itself. + - E.g. Using this on a trait such as `trait Foo { ... }` will result in the + generated impl incorrectly missing the `T` generic. + +If your trait fits these criteria then `make_trait_impl` is likely the easiest +way to write your derive handler. The arguments are as follows: + +- `s`: The struct to make the impl for +- `trait_name`: The name of the trait to derive. E.g. `quote { Eq }`. +- `function_signature`: The signature of the trait method to derive. E.g. `fn eq(self, other: Self) -> bool`. +- `for_each_field`: An operation to be performed on each field. E.g. `|name| quote { (self.$name == other.$name) }`. +- `join_fields_with`: A separator to join each result of `for_each_field` with. + E.g. `quote { & }`. You can also use an empty `quote {}` for no separator. +- `body`: The result of the field operations are passed into this function for any final processing. + This is the place to insert any setup/teardown code the trait requires. If the trait doesn't require + any such code, you can return the body as-is: `|body| body`. + +Example deriving `Hash`: + +```rust title="derive_hash" showLineNumbers +comptime fn derive_hash(s: StructDefinition) -> Quoted { + let name = quote { Hash }; + let signature = quote { fn hash(_self: Self, _state: &mut H) where H: std::hash::Hasher }; + let for_each_field = |name| quote { _self.$name.hash(_state); }; + crate::meta::make_trait_impl( + s, + name, + signature, + for_each_field, + quote {}, + |fields| fields, + ) +} +``` +> Source code: noir_stdlib/src/hash/mod.nr#L137-L151 + + +Example deriving `Ord`: + +```rust title="derive_ord" showLineNumbers +comptime fn derive_ord(s: StructDefinition) -> Quoted { + let signature = quote { fn cmp(_self: Self, _other: Self) -> std::cmp::Ordering }; + let for_each_field = |name| quote { + if result == std::cmp::Ordering::equal() { + result = _self.$name.cmp(_other.$name); + } + }; + let body = |fields| quote { + let mut result = std::cmp::Ordering::equal(); + $fields + result + }; + crate::meta::make_trait_impl(s, quote { Ord }, signature, for_each_field, quote {}, body) +} +``` +> Source code: noir_stdlib/src/cmp.nr#L216-L231 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/module.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/module.md new file mode 100644 index 00000000000..f47231972b7 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/module.md @@ -0,0 +1,82 @@ +--- +title: Module +--- + +`std::meta::module` contains methods on the built-in `Module` type which represents a module in the source program. +Note that this type represents a module generally, it isn't limited to only `mod my_submodule { ... }` +declarations in the source program. + +## Methods + +### add_item + +```rust title="add_item" showLineNumbers +pub comptime fn add_item(self, item: Quoted) {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L3-L5 + + +Adds a top-level item (a function, a struct, a global, etc.) to the module. +Adding multiple items in one go is also valid if the `Quoted` value has multiple items in it. +Note that the items are type-checked as if they are inside the module they are being added to. + +### functions + +```rust title="functions" showLineNumbers +pub comptime fn functions(self) -> [FunctionDefinition] {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L18-L20 + + +Returns each function defined in the module. + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +pub comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L8-L10 + + +Returns true if this module has a custom attribute with the given name. + +### is_contract + +```rust title="is_contract" showLineNumbers +pub comptime fn is_contract(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L13-L15 + + +`true` if this module is a contract module (was declared via `contract foo { ... }`). + +### name + +```rust title="name" showLineNumbers +pub comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L28-L30 + + +Returns the name of the module. + +### structs + +```rust title="structs" showLineNumbers +pub comptime fn structs(self) -> [StructDefinition] {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L23-L25 + + +Returns each struct defined in the module. + +## Trait Implementations + +```rust +impl Eq for Module +impl Hash for Module +``` + +Note that each module is assigned a unique ID internally and this is what is used for +equality and hashing. So even modules with identical names and contents may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/op.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/op.md new file mode 100644 index 00000000000..03ea49ad8ec --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/op.md @@ -0,0 +1,244 @@ +--- +title: UnaryOp and BinaryOp +--- + +`std::meta::op` contains the `UnaryOp` and `BinaryOp` types as well as methods on them. +These types are used to represent a unary or binary operator respectively in Noir source code. + +## Types + +### UnaryOp + +Represents a unary operator. One of `-`, `!`, `&mut`, or `*`. + +### Methods + +#### is_minus + +```rust title="is_minus" showLineNumbers +pub fn is_minus(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L24-L26 + + +Returns `true` if this operator is `-`. + +#### is_not + +```rust title="is_not" showLineNumbers +pub fn is_not(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L30-L32 + + +`true` if this operator is `!` + +#### is_mutable_reference + +```rust title="is_mutable_reference" showLineNumbers +pub fn is_mutable_reference(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L36-L38 + + +`true` if this operator is `&mut` + +#### is_dereference + +```rust title="is_dereference" showLineNumbers +pub fn is_dereference(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L42-L44 + + +`true` if this operator is `*` + +#### quoted + +```rust title="unary_quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/op.nr#L48-L50 + + +Returns this operator as a `Quoted` value. + +### Trait Implementations + +```rust +impl Eq for UnaryOp +impl Hash for UnaryOp +``` + +### BinaryOp + +Represents a binary operator. One of `+`, `-`, `*`, `/`, `%`, `==`, `!=`, `<`, `<=`, `>`, `>=`, `&`, `|`, `^`, `>>`, or `<<`. + +### Methods + +#### is_add + +```rust title="is_add" showLineNumbers +pub fn is_add(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L86-L88 + + +`true` if this operator is `+` + +#### is_subtract + +```rust title="is_subtract" showLineNumbers +pub fn is_subtract(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L92-L94 + + +`true` if this operator is `-` + +#### is_multiply + +```rust title="is_multiply" showLineNumbers +pub fn is_multiply(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L98-L100 + + +`true` if this operator is `*` + +#### is_divide + +```rust title="is_divide" showLineNumbers +pub fn is_divide(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L104-L106 + + +`true` if this operator is `/` + +#### is_modulo + +```rust title="is_modulo" showLineNumbers +pub fn is_modulo(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L176-L178 + + +`true` if this operator is `%` + +#### is_equal + +```rust title="is_equal" showLineNumbers +pub fn is_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L110-L112 + + +`true` if this operator is `==` + +#### is_not_equal + +```rust title="is_not_equal" showLineNumbers +pub fn is_not_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L116-L118 + + +`true` if this operator is `!=` + +#### is_less_than + +```rust title="is_less_than" showLineNumbers +pub fn is_less_than(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L122-L124 + + +`true` if this operator is `<` + +#### is_less_than_or_equal + +```rust title="is_less_than_or_equal" showLineNumbers +pub fn is_less_than_or_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L128-L130 + + +`true` if this operator is `<=` + +#### is_greater_than + +```rust title="is_greater_than" showLineNumbers +pub fn is_greater_than(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L134-L136 + + +`true` if this operator is `>` + +#### is_greater_than_or_equal + +```rust title="is_greater_than_or_equal" showLineNumbers +pub fn is_greater_than_or_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L140-L142 + + +`true` if this operator is `>=` + +#### is_and + +```rust title="is_and" showLineNumbers +pub fn is_and(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L146-L148 + + +`true` if this operator is `&` + +#### is_or + +```rust title="is_or" showLineNumbers +pub fn is_or(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L152-L154 + + +`true` if this operator is `|` + +#### is_shift_right + +```rust title="is_shift_right" showLineNumbers +pub fn is_shift_right(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L164-L166 + + +`true` if this operator is `>>` + +#### is_shift_left + +```rust title="is_shift_right" showLineNumbers +pub fn is_shift_right(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L164-L166 + + +`true` if this operator is `<<` + +#### quoted + +```rust title="binary_quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/op.nr#L182-L184 + + +Returns this operator as a `Quoted` value. + +### Trait Implementations + +```rust +impl Eq for BinaryOp +impl Hash for BinaryOp +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/quoted.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/quoted.md new file mode 100644 index 00000000000..d7acf23bc07 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/quoted.md @@ -0,0 +1,141 @@ +--- +title: Quoted +--- + +`std::meta::quoted` contains methods on the built-in `Quoted` type which represents +quoted token streams and is the result of the `quote { ... }` expression. + +## Methods + +### as_expr + +```rust title="as_expr" showLineNumbers +pub comptime fn as_expr(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L6-L8 + + +Parses the quoted token stream as an expression. Returns `Option::none()` if +the expression failed to parse. + +Example: + +```rust title="as_expr_example" showLineNumbers +#[test] + fn test_expr_as_function_call() { + comptime + { + let expr = quote { foo(42) }.as_expr().unwrap(); + let (_function, args) = expr.as_function_call().unwrap(); + assert_eq(args.len(), 1); + assert_eq(args[0].as_integer().unwrap(), (42, false)); + } + } +``` +> Source code: test_programs/noir_test_success/comptime_expr/src/main.nr#L360-L371 + + +### as_module + +```rust title="as_module" showLineNumbers +pub comptime fn as_module(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L11-L13 + + +Interprets this token stream as a module path leading to the name of a module. +Returns `Option::none()` if the module isn't found or this token stream cannot be parsed as a path. + +Example: + +```rust title="as_module_example" showLineNumbers +mod baz { + pub mod qux {} +} + +#[test] +fn as_module_test() { + comptime { + let my_mod = quote { baz::qux }.as_module().unwrap(); + assert_eq(my_mod.name(), quote { qux }); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_module/src/main.nr#L115-L127 + + +### as_trait_constraint + +```rust title="as_trait_constraint" showLineNumbers +pub comptime fn as_trait_constraint(self) -> TraitConstraint {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L16-L18 + + +Interprets this token stream as a trait constraint (without an object type). +Note that this function panics instead of returning `Option::none()` if the token +stream does not parse and resolve to a valid trait constraint. + +Example: + +```rust title="implements_example" showLineNumbers +pub fn function_with_where(_x: T) +where + T: SomeTrait, +{ + comptime { + let t = quote { T }.as_type(); + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + assert(t.implements(some_trait_i32)); + + assert(t.get_trait_impl(some_trait_i32).is_none()); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L160-L173 + + +### as_type + +```rust title="as_type" showLineNumbers +pub comptime fn as_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L21-L23 + + +Interprets this token stream as a resolved type. Panics if the token +stream doesn't parse to a type or if the type isn't a valid type in scope. + +```rust title="implements_example" showLineNumbers +pub fn function_with_where(_x: T) +where + T: SomeTrait, +{ + comptime { + let t = quote { T }.as_type(); + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + assert(t.implements(some_trait_i32)); + + assert(t.get_trait_impl(some_trait_i32).is_none()); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L160-L173 + + +### tokens + +```rust title="tokens" showLineNumbers +pub comptime fn tokens(self) -> [Quoted] {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L26-L28 + + +Returns a slice of the individual tokens that form this token stream. + +## Trait Implementations + +```rust +impl Eq for Quoted +impl Hash for Quoted +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/struct_def.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/struct_def.md new file mode 100644 index 00000000000..fd609942f4e --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/struct_def.md @@ -0,0 +1,177 @@ +--- +title: StructDefinition +--- + +`std::meta::struct_def` contains methods on the built-in `StructDefinition` type. +This type corresponds to `struct Name { field1: Type1, ... }` items in the source program. + +## Methods + +### add_attribute + +```rust title="add_attribute" showLineNumbers +pub comptime fn add_attribute(self, attribute: str) {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L3-L5 + + +Adds an attribute to the struct. + +### add_generic + +```rust title="add_generic" showLineNumbers +pub comptime fn add_generic(self, generic_name: str) -> Type {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L8-L10 + + +Adds an generic to the struct. Returns the new generic type. +Errors if the given generic name isn't a single identifier or if +the struct already has a generic with the same name. + +This method should be used carefully, if there is existing code referring +to the struct type it may be checked before this function is called and +see the struct with the original number of generics. This method should +thus be preferred to use on code generated from other macros and structs +that are not used in function signatures. + +Example: + +```rust title="add-generic-example" showLineNumbers +comptime fn add_generic(s: StructDefinition) { + assert_eq(s.generics().len(), 0); + let new_generic = s.add_generic("T"); + + let generics = s.generics(); + assert_eq(generics.len(), 1); + assert_eq(generics[0], new_generic); + } +``` +> Source code: test_programs/compile_success_empty/comptime_struct_definition/src/main.nr#L35-L44 + + +### as_type + +```rust title="as_type" showLineNumbers +pub comptime fn as_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L15-L17 + + +Returns this struct as a type in the source program. If this struct has +any generics, the generics are also included as-is. + +### generics + +```rust title="generics" showLineNumbers +pub comptime fn generics(self) -> [Type] {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L26-L28 + + +Returns each generic on this struct. + +Example: + +``` +#[example] +struct Foo { + bar: [T; 2], + baz: Baz, +} + +comptime fn example(foo: StructDefinition) { + assert_eq(foo.generics().len(), 2); + + // Fails because `T` isn't in scope + // let t = quote { T }.as_type(); + // assert_eq(foo.generics()[0], t); +} +``` + +### fields + +```rust title="fields" showLineNumbers +pub comptime fn fields(self) -> [(Quoted, Type)] {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L33-L35 + + +Returns each field of this struct as a pair of (field name, field type). + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +pub comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L20-L22 + + +Returns true if this struct has a custom attribute with the given name. + +### module + +```rust title="module" showLineNumbers +pub comptime fn module(self) -> Module {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L38-L40 + + +Returns the module where the struct is defined. + +### name + +```rust title="name" showLineNumbers +pub comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L43-L45 + + +Returns the name of this struct + +Note that the returned quoted value will be just the struct name, it will +not be the full path to the struct, nor will it include any generics. + +### set_fields + +```rust title="set_fields" showLineNumbers +pub comptime fn set_fields(self, new_fields: [(Quoted, Type)]) {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L52-L54 + + +Sets the fields of this struct to the given fields list where each element +is a pair of the field's name and the field's type. Expects each field name +to be a single identifier. Note that this will override any previous fields +on this struct. If those should be preserved, use `.fields()` to retrieve the +current fields on the struct type and append the new fields from there. + +Example: + +```rust +// Change this struct to: +// struct Foo { +// a: u32, +// b: i8, +// } +#[mangle_fields] +struct Foo { x: Field } + +comptime fn mangle_fields(s: StructDefinition) { + s.set_fields(&[ + (quote { a }, quote { u32 }.as_type()), + (quote { b }, quote { i8 }.as_type()), + ]); +} +``` + +## Trait Implementations + +```rust +impl Eq for StructDefinition +impl Hash for StructDefinition +``` + +Note that each struct is assigned a unique ID internally and this is what is used for +equality and hashing. So even structs with identical generics and fields may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/trait_constraint.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/trait_constraint.md new file mode 100644 index 00000000000..3106f732b5a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/trait_constraint.md @@ -0,0 +1,17 @@ +--- +title: TraitConstraint +--- + +`std::meta::trait_constraint` contains methods on the built-in `TraitConstraint` type which represents +a trait constraint that can be used to search for a trait implementation. This is similar +syntactically to just the trait itself, but can also contain generic arguments. E.g. `Eq`, `Default`, +`BuildHasher`. + +This type currently has no public methods but it can be used alongside `Type` in `implements` or `get_trait_impl`. + +## Trait Implementations + +```rust +impl Eq for TraitConstraint +impl Hash for TraitConstraint +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/trait_def.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/trait_def.md new file mode 100644 index 00000000000..e661d3af7f1 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/trait_def.md @@ -0,0 +1,26 @@ +--- +title: TraitDefinition +--- + +`std::meta::trait_def` contains methods on the built-in `TraitDefinition` type. This type +represents trait definitions such as `trait Foo { .. }` at the top-level of a program. + +## Methods + +### as_trait_constraint + +```rust title="as_trait_constraint" showLineNumbers +pub comptime fn as_trait_constraint(_self: Self) -> TraitConstraint {} +``` +> Source code: noir_stdlib/src/meta/trait_def.nr#L6-L8 + + +Converts this trait into a trait constraint. If there are any generics on this +trait, they will be kept as-is without instantiating or replacing them. + +## Trait Implementations + +```rust +impl Eq for TraitDefinition +impl Hash for TraitDefinition +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/trait_impl.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/trait_impl.md new file mode 100644 index 00000000000..a527617c1e6 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/trait_impl.md @@ -0,0 +1,60 @@ +--- +title: TraitImpl +--- + +`std::meta::trait_impl` contains methods on the built-in `TraitImpl` type which represents a trait +implementation such as `impl Foo for Bar { ... }`. + +## Methods + +### trait_generic_args + +```rust title="trait_generic_args" showLineNumbers +pub comptime fn trait_generic_args(self) -> [Type] {} +``` +> Source code: noir_stdlib/src/meta/trait_impl.nr#L3-L5 + + +Returns any generic arguments on the trait of this trait implementation, if any. + +```rs +impl Foo for Bar { ... } + +comptime { + let bar_type = quote { Bar }.as_type(); + let foo = quote { Foo }.as_trait_constraint(); + + let my_impl: TraitImpl = bar_type.get_trait_impl(foo).unwrap(); + + let generics = my_impl.trait_generic_args(); + assert_eq(generics.len(), 2); + + assert_eq(generics[0], quote { i32 }.as_type()); + assert_eq(generics[1], quote { Field }.as_type()); +} +``` + +### methods + +```rust title="methods" showLineNumbers +pub comptime fn methods(self) -> [FunctionDefinition] {} +``` +> Source code: noir_stdlib/src/meta/trait_impl.nr#L8-L10 + + +Returns each method in this trait impl. + +Example: + +```rs +comptime { + let i32_type = quote { i32 }.as_type(); + let eq = quote { Eq }.as_trait_constraint(); + + let impl_eq_for_i32: TraitImpl = i32_type.get_trait_impl(eq).unwrap(); + let methods = impl_eq_for_i32.methods(); + + assert_eq(methods.len(), 1); + assert_eq(methods[0].name(), quote { eq }); +} +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/typ.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/typ.md new file mode 100644 index 00000000000..90222c222f5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/typ.md @@ -0,0 +1,264 @@ +--- +title: Type +--- + +`std::meta::typ` contains methods on the built-in `Type` type used for representing +a type in the source program. + +## Functions + +```rust title="fresh_type_variable" showLineNumbers +pub comptime fn fresh_type_variable() -> Type {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L57-L59 + + +Creates and returns an unbound type variable. This is a special kind of type internal +to type checking which will type check with any other type. When it is type checked +against another type it will also be set to that type. For example, if `a` is a type +variable and we have the type equality `(a, i32) = (u8, i32)`, the compiler will set +`a` equal to `u8`. + +Unbound type variables will often be rendered as `_` while printing them. Bound type +variables will appear as the type they are bound to. + +This can be used in conjunction with functions which internally perform type checks +such as `Type::implements` or `Type::get_trait_impl` to potentially grab some of the types used. + +Note that calling `Type::implements` or `Type::get_trait_impl` on a type variable will always +fail. + +Example: + +```rust title="serialize-setup" showLineNumbers +trait Serialize {} + +impl Serialize<1> for Field {} + +impl Serialize for [T; N] +where + T: Serialize, +{} + +impl Serialize for (T, U) +where + T: Serialize, + U: Serialize, +{} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L14-L29 + +```rust title="fresh-type-variable-example" showLineNumbers +let typevar1 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar1> }.as_trait_constraint(); + let field_type = quote { Field }.as_type(); + + // Search for a trait impl (binding typevar1 to 1 when the impl is found): + assert(field_type.implements(constraint)); + + // typevar1 should be bound to the "1" generic now: + assert_eq(typevar1.as_constant().unwrap(), 1); + + // If we want to do the same with a different type, we need to + // create a new type variable now that `typevar1` is bound + let typevar2 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar2> }.as_trait_constraint(); + let array_type = quote { [(Field, Field); 5] }.as_type(); + assert(array_type.implements(constraint)); + + // Now typevar2 should be bound to the serialized pair size 2 times the array length 5 + assert_eq(typevar2.as_constant().unwrap(), 10); +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L129-L149 + + +## Methods + +### as_array + +```rust title="as_array" showLineNumbers +pub comptime fn as_array(self) -> Option<(Type, Type)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L76-L78 + + +If this type is an array, return a pair of (element type, size type). + +Example: + +```rust +comptime { + let array_type = quote { [Field; 3] }.as_type(); + let (field_type, three_type) = array_type.as_array().unwrap(); + + assert(field_type.is_field()); + assert_eq(three_type.as_constant().unwrap(), 3); +} +``` + +### as_constant + +```rust title="as_constant" showLineNumbers +pub comptime fn as_constant(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L83-L85 + + +If this type is a constant integer (such as the `3` in the array type `[Field; 3]`), +return the numeric constant. + +### as_integer + +```rust title="as_integer" showLineNumbers +pub comptime fn as_integer(self) -> Option<(bool, u8)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L90-L92 + + +If this is an integer type, return a boolean which is `true` +if the type is signed, as well as the number of bits of this integer type. + +### as_mutable_reference + +```rust title="as_mutable_reference" showLineNumbers +comptime fn as_mutable_reference(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L96-L98 + + +If this is a mutable reference type `&mut T`, returns the mutable type `T`. + +### as_slice + +```rust title="as_slice" showLineNumbers +pub comptime fn as_slice(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L102-L104 + + +If this is a slice type, return the element type of the slice. + +### as_str + +```rust title="as_str" showLineNumbers +pub comptime fn as_str(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L108-L110 + + +If this is a `str` type, returns the length `N` as a type. + +### as_struct + +```rust title="as_struct" showLineNumbers +pub comptime fn as_struct(self) -> Option<(StructDefinition, [Type])> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L114-L116 + + +If this is a struct type, returns the struct in addition to +any generic arguments on this type. + +### as_tuple + +```rust title="as_tuple" showLineNumbers +pub comptime fn as_tuple(self) -> Option<[Type]> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L120-L122 + + +If this is a tuple type, returns each element type of the tuple. + +### get_trait_impl + +```rust title="get_trait_impl" showLineNumbers +pub comptime fn get_trait_impl(self, constraint: TraitConstraint) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L143-L145 + + +Retrieves the trait implementation that implements the given +trait constraint for this type. If the trait constraint is not +found, `None` is returned. Note that since the concrete trait implementation +for a trait constraint specified from a `where` clause is unknown, +this function will return `None` in these cases. If you only want to know +whether a type implements a trait, use `implements` instead. + +Example: + +```rust +comptime { + let field_type = quote { Field }.as_type(); + let default = quote { Default }.as_trait_constraint(); + + let the_impl: TraitImpl = field_type.get_trait_impl(default).unwrap(); + assert(the_impl.methods().len(), 1); +} +``` + +### implements + +```rust title="implements" showLineNumbers +pub comptime fn implements(self, constraint: TraitConstraint) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L166-L168 + + +`true` if this type implements the given trait. Note that unlike +`get_trait_impl` this will also return true for any `where` constraints +in scope. + +Example: + +```rust +fn foo() where T: Default { + comptime { + let field_type = quote { Field }.as_type(); + let default = quote { Default }.as_trait_constraint(); + assert(field_type.implements(default)); + + let t = quote { T }.as_type(); + assert(t.implements(default)); + } +} +``` + +### is_bool + +```rust title="is_bool" showLineNumbers +pub comptime fn is_bool(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L172-L174 + + +`true` if this type is `bool`. + +### is_field + +```rust title="is_field" showLineNumbers +pub comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L178-L180 + + +`true` if this type is `Field`. + +### is_unit + +```rust title="is_unit" showLineNumbers +comptime fn is_unit(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L184-L186 + + +`true` if this type is the unit `()` type. + +## Trait Implementations + +```rust +impl Eq for Type +impl Hash for Type +``` +Note that this is syntactic equality, this is not the same as whether two types will type check +to be the same type. Unless type inference or generics are being used however, users should not +typically have to worry about this distinction unless `std::meta::typ::fresh_type_variable` is used. diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/typed_expr.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/typed_expr.md new file mode 100644 index 00000000000..0db7dbfef61 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/typed_expr.md @@ -0,0 +1,27 @@ +--- +title: TypedExpr +--- + +`std::meta::typed_expr` contains methods on the built-in `TypedExpr` type for resolved and type-checked expressions. + +## Methods + +### get_type + +```rust title="as_function_definition" showLineNumbers +pub comptime fn as_function_definition(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typed_expr.nr#L7-L9 + + +If this expression refers to a function definitions, returns it. Otherwise returns `Option::none()`. + +### get_type + +```rust title="get_type" showLineNumbers +pub comptime fn get_type(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typed_expr.nr#L13-L15 + + +Returns the type of the expression, or `Option::none()` if there were errors when the expression was previously resolved. \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/unresolved_type.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/unresolved_type.md new file mode 100644 index 00000000000..2826ec5ec0f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/meta/unresolved_type.md @@ -0,0 +1,57 @@ +--- +title: UnresolvedType +--- + +`std::meta::unresolved_type` contains methods on the built-in `UnresolvedType` type for the syntax of types. + +## Methods + +### as_mutable_reference + +```rust title="as_mutable_reference" showLineNumbers +comptime fn as_mutable_reference(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L8-L10 + + +If this is a mutable reference type `&mut T`, returns the mutable type `T`. + +### as_slice + +```rust title="as_slice" showLineNumbers +comptime fn as_slice(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L14-L16 + + +If this is a slice `&[T]`, returns the element type `T`. + +### is_bool + +```rust title="is_bool" showLineNumbers +comptime fn is_bool(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L20-L22 + + +Returns `true` if this type is `bool`. + +### is_field + +```rust title="is_field" showLineNumbers +pub comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L26-L28 + + +Returns true if this type refers to the Field type. + +### is_unit + +```rust title="is_unit" showLineNumbers +comptime fn is_unit(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L32-L34 + + +Returns true if this type is the unit `()` type. diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/options.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/noir/standard_library/recursion.mdx b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/recursion.mdx new file mode 100644 index 00000000000..fcb36278060 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/recursion.mdx @@ -0,0 +1,67 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, verify_proof] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox'; + +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) + +## Verifying Recursive Proofs + +```rust +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} +``` + + + +## Example usage + +```rust + +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, + proof, + public_inputs, + key_hash + ); + + std::verify_proof( + verification_key, + proof_b, + public_inputs, + 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-v1.0.0-beta.0/noir/standard_library/traits.md b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..ee20f9cd949 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/noir/standard_library/traits.md @@ -0,0 +1,628 @@ +--- +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 +pub trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L4-L8 + + +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 +pub 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#L28-L119 + + +#### 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 +pub 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-L26 + + +`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 +pub trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L4-L8 + + +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 +pub trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L210-L214 + + +`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 +pub trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +pub trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L60-L64 + +```rust title="mul-trait" showLineNumbers +pub trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L119-L123 + +```rust title="div-trait" showLineNumbers +pub trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L178-L182 + + +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 +pub trait Rem { + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L237-L241 + + +`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 +pub trait Neg { + fn neg(self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L290-L294 + + +`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#L296-L323 + + +### `std::ops::Not` + +```rust title="not-trait" showLineNumbers +pub 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-L60 + + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +pub trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L62-L66 + +```rust title="bitand-trait" showLineNumbers +pub trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L121-L125 + +```rust title="bitxor-trait" showLineNumbers +pub trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L180-L184 + + +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 +pub trait Shl { + fn shl(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L239-L243 + +```rust title="shr-trait" showLineNumbers +pub trait Shr { + fn shr(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L292-L296 + + +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 } } +``` + +--- + +## `std::append` + +### `std::append::Append` + +`Append` can abstract over types that can be appended to - usually container types: + +```rust title="append-trait" showLineNumbers +pub trait Append { + fn empty() -> Self; + fn append(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/append.nr#L9-L14 + + +`Append` requires two methods: + +- `empty`: Constructs an empty value of `Self`. +- `append`: Append two values together, returning the result. + +Additionally, it is expected that for any implementation: + +- `T::empty().append(x) == x` +- `x.append(T::empty()) == x` + +Implementations: +```rust +impl Append for [T] +impl Append for Quoted +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..ead255bc504 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,52 @@ +# Noir + +## Constructors + +### new Noir(circuit) + +```ts +new Noir(circuit): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### 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) +``` + +*** + +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-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..5e3cd53e9d3 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..4de7a696991 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,47 @@ +# 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. | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +## References + +### CompiledCircuit + +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-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md new file mode 100644 index 00000000000..e8c2f4aef3d --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..4796b5abaa8 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_wasm/.nojekyll b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_wasm/functions/compile.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_wasm/index.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/docs/versioned_docs/version-v1.0.0-beta.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/reference/debugger/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.0/reference/debugger/_category_.json new file mode 100644 index 00000000000..27869205ad3 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/reference/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugger", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/reference/debugger/debugger_known_limitations.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/debugger/debugger_known_limitations.md new file mode 100644 index 00000000000..936d416ac4b --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/debugger/debugger_repl.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/debugger/debugger_repl.md new file mode 100644 index 00000000000..46e2011304e --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/debugger/debugger_vscode.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/debugger/debugger_vscode.md new file mode 100644 index 00000000000..c027332b3b0 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/reference/nargo_commands.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/nargo_commands.md new file mode 100644 index 00000000000..8842fad6647 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/reference/nargo_commands.md @@ -0,0 +1,474 @@ +--- +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 check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo debug`↴](#nargo-debug) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) +* [`nargo generate-completion-script`↴](#nargo-generate-completion-script) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `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 +* `debug` — Executes a circuit in debug mode +* `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 +* `generate-completion-script` — Generates a shell completion script for your favorite shell + +###### **Options:** + + + + +## `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 + + Possible values: `true`, `false` + +* `--overwrite` — Force overwrite of existing files + + Possible values: `true`, `false` + +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--bin` — Use a binary template [default] + + Possible values: `true`, `false` + +* `--contract` — Use a contract template + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--bin` — Use a binary template [default] + + Possible values: `true`, `false` + +* `--contract` — Use a contract template + + Possible values: `true`, `false` + + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +Defaults to the name of the package being executed. + +###### **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 + + Possible values: `true`, `false` + +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo debug` + +Executes a circuit in debug mode + +**Usage:** `nargo debug [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 +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--acir-mode` — Force ACIR output (disabling instrumentation) + + Possible values: `true`, `false` + +* `--skip-instrumentation ` — Disable vars debug instrumentation (enabled by default) + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--exact` — Only run tests that match exactly + + Possible values: `true`, `false` + +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace + + Possible values: `true`, `false` + +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--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 + + Possible values: `true`, `false` + +* `--profile-execution` + + Possible values: `true`, `false` + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + + + + +## `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` + + + +## `nargo generate-completion-script` + +Generates a shell completion script for your favorite shell + +**Usage:** `nargo generate-completion-script ` + +###### **Arguments:** + +* `` — The shell to generate completions for. One of: bash, elvish, fish, powershell, zsh + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/reference/noir_codegen.md b/docs/versioned_docs/version-v1.0.0-beta.0/reference/noir_codegen.md new file mode 100644 index 00000000000..e4c362f9610 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/reference/noir_codegen.md @@ -0,0 +1,116 @@ +--- +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](../getting_started/noir_installation.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"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"}},"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-v1.0.0-beta.0/tooling/debugger.md b/docs/versioned_docs/version-v1.0.0-beta.0/tooling/debugger.md new file mode 100644 index 00000000000..200b5fc423a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/tooling/debugger.md @@ -0,0 +1,26 @@ +--- +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/noir_installation.md) and vscode-noir: + +- Noir & Nargo ≥0.28.0 +- Noir's VS Code extension ≥0.0.11 + +:::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-v1.0.0-beta.0/tooling/language_server.md b/docs/versioned_docs/version-v1.0.0-beta.0/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.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-v1.0.0-beta.0/tooling/testing.md b/docs/versioned_docs/version-v1.0.0-beta.0/tooling/testing.md new file mode 100644 index 00000000000..866677da567 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/tooling/testing.md @@ -0,0 +1,79 @@ +--- +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); +} +``` + +The string given to `should_fail_with` doesn't need to exactly match the failure reason, it just needs to be a substring of it: + +```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 = "airspeed velocity")] +fn test_bridgekeeper() { + main(32); +} +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.0/tutorials/noirjs_app.md b/docs/versioned_docs/version-v1.0.0-beta.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..8967ee005ce --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.0/tutorials/noirjs_app.md @@ -0,0 +1,306 @@ +--- +title: Building a web app with Noir and Barretenberg +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 Typescript package meant to work both in a browser and a server environment. + +In this tutorial, we will combine NoirJS with Aztec's Barretenberg backend to build a simple web app. 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). + +## Dependencies + +Before we start, we want to make sure we have Node installed. For convenience (and speed), we can just install [Bun](https://bun.sh) as our package manager, and Node will work out-of-the-box: + +```bash +curl -fsSL https://bun.sh/install | bash +``` + +Let's go barebones. Doing the bare minimum is not only simple, but also allows you to easily adapt it to almost any frontend framework. + +Barebones means we can immediately start with the dependencies even on an empty folder 😈: + +```bash +bun i @noir-lang/noir_wasm@1.0.0-beta.0 @noir-lang/noir_js@1.0.0-beta.0 @aztec/bb.js@0.63.1 +``` + +Wait, what are these dependencies? + +- `noir_wasm` is the `wasm` version of the Noir compiler. Although most developers prefer to use `nargo` for compiling, there's nothing wrong with `noir_wasm`. We like `noir_wasm`. +- `noir_js` is the main Noir package. It will execute our program, and generate the witness that will be sent to the backend. +- `bb.js` is the Typescript interface for Aztec's Barretenberg proving backend. It also uses the `wasm` version in order to run on the browser. + +:::info + +In this guide, we will install versions pinned to 1.0.0-beta.0. These work with Barretenberg version 0.63.1, so we are using that one version too. Feel free to try with older or later versions, though! + +::: + +## Setting up our Noir program + +ZK is a powerful technology. An app that reveals computational correctness but doesn't reveal some of its inputs is almost unbelievable, yet Noir makes it as easy as a single line of code. + +:::tip + +It's not just you. We also enjoy syntax highlighting. [Check out the Language Server](../tooling/language_server.md) + +::: + +All you need is a `main.nr` and a `Nargo.toml` file. You can follow the [noirup](../getting_started/noir_installation.md) installation and just run `noirup -v 1.0.0-beta.0`, or just create them by hand: + +```bash +mkdir -p circuit/src +touch circuit/src/main.nr circuit/Nargo.toml +``` + +To make our program interesting, let's give it a real use-case scenario: Bob wants to prove he is older than 18, without disclosing his age. Open `main.nr` and write: + +```rust +fn main(age: u8) { + assert(age >= 18); +} +``` + +This program accepts a private input called age, and simply proves this number is higher than 18. But to run this code, we need to give the compiler a `Nargo.toml` with at least a name and a type: + +```toml +[package] +name = "circuit" +type = "bin" +``` + +This is all that we need to get started with Noir. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## Setting up our app + +Remember when apps only had one `html` and one `js` file? Well, that's enough for Noir webapps. Let's create them: + +```bash +touch index.html index.js +``` + +And add something useful to our HTML file: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It _could_ be a beautiful UI... Depending on which universe you live in. In any case, we're using some scary CSS to make two boxes that will show cool things on the screen. + +As for the JS, real madmen could just `console.log` everything, but let's say we want to see things happening (the true initial purpose of JS... right?). Here's some boilerplate for that. Just paste it in `index.js`: + +```js +const show = (id, content) => { + const container = document.getElementById(id); + container.appendChild(document.createTextNode(content)); + container.appendChild(document.createElement("br")); +}; + +document.getElementById("submit").addEventListener("click", async () => { + try { + // noir goes here + } catch { + show("logs", "Oh 💔"); + } +}); + +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── src + └── main.nr + Nargo.toml + index.js + package.json + index.html + ...etc +``` + +::: + +## Compile compile compile + +Finally we're up for something cool. But before we can execute a Noir program, we need to compile it into ACIR: an abstract representation. Here's where `noir_wasm` comes in. + +`noir_wasm` expects a filesystem so it can resolve dependencies. While we could use the `public` folder, let's just import those using the nice `?url` syntax provided by vite. At the top of the file: + +```js +import { compile, createFileManager } from "@noir-lang/noir_wasm" + +import main from "./circuit/src/main.nr?url"; +import nargoToml from "./circuit/Nargo.toml?url"; +``` + +Compiling on the browser is common enough that `createFileManager` already gives us a nice in-memory filesystem we can use. So all we need to compile is fetching these files, writing them to our filesystem, and compile. Add this function: + +```js +export async function getCircuit() { + const fm = createFileManager("/"); + const { body } = await fetch(main); + const { body: nargoTomlBody } = await fetch(nargoToml); + + fm.writeFile("./src/main.nr", body); + fm.writeFile("./Nargo.toml", nargoTomlBody); + return await compile(fm); +} +``` + +:::tip + +As you can imagine, with `node` it's all conveniently easier since you get native access to `fs`... + +::: + +## Some more JS + +We're starting with the good stuff now. We want to execute our circuit to get the witness, and then feed that witness to Barretenberg. Luckily, both packages are quite easy to work with. Let's import them at the top of the file: + +```js +import { UltraHonkBackend } from '@aztec/bb.js'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const { program } = await getCircuit(); +const noir = new Noir(program); +const backend = new UltraHonkBackend(program.bytecode); +// } +``` + +:::warning + +WASMs are not always easy to work with. In our case, `vite` likes serving them with the wrong MIME type. There are different fixes but we found the easiest one is just YOLO instantiating the WASMs manually. Paste this at the top of the file, just below the other imports, and it will work just fine: + +```js +import initNoirC from "@noir-lang/noirc_abi"; +import initACVM from "@noir-lang/acvm_js"; +import acvm from "@noir-lang/acvm_js/web/acvm_js_bg.wasm?url"; +import noirc from "@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm?url"; +await Promise.all([initACVM(fetch(acvm)), initNoirC(fetch(noirc))]); +``` + +::: + +## Executing and proving + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Inside our `try` block, let's just grab that input and get its value. Noir will gladly execute it, and give us a witness: + +```js +const age = document.getElementById("age").value; +show("logs", "Generating witness... ⏳"); +const { witness } = await noir.execute({ age }); +show("logs", "Generated witness... ✅"); + +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +show("logs", "Generating proof... ⏳"); +const proof = await backend.generateProof(witness); +show("logs", "Generated proof... ✅"); +show("results", proof.proof); +``` + +Our program is technically **done** . You're probably eager to see stuff happening! To serve this in a convenient way, we can use a bundler like `vite` by creating a `vite.config.js` file: + +```bash +touch vite.config.js +``` + +`vite` helps us with a little catch: `bb.js` in particular uses top-level awaits which aren't supported everywhere. So we can add this to the `vite.config.js` to make the bundler optimize them: + +```js +export default { optimizeDeps: { esbuildOptions: { target: "esnext" } } }; +``` + +This should be enough for vite. We don't even need to install it, just run: + +```bash +bunx vite +``` + +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. + +![Noir Webapp UI](@site/static/img/tutorials/noirjs_webapp/webapp1.png) + +Now, our circuit requires a private input `fn main(age: u8)`, and fails if it is less than 18. Let's see if it works. Submit any number above 18 (as long as it fits in 8 bits) and 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 +show('logs', 'Verifying proof... ⌛'); +const isValid = await backend.verifyProof(proof); +show("logs", `Proof is ${isValid ? "valid" : "invalid"}... ✅`); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## Next steps + +At this point, you have a working ZK app that works on the browser. Actually, it works on a mobile phone too! + +If you want to continue learning by doing, here are some challenges for you: + +- Install [nargo](https://noir-lang.org/docs/getting_started/noir_installation) and write [Noir tests](../tooling/testing) +- Change the circuit to accept a [public input](../noir/concepts/data_types/#private--public-types) as the cutoff age. It could be different depending on the purpose, for example! +- Enjoy Noir's Rust-like syntax and write a struct `Country` that implements a trait `MinAge` with a method `get_min_age`. Then, make a struct `Person` have an `u8` as its age and a country of type `Country`. You can pass a `person` in JS just like a JSON object `person: { age, country: { min_age: 18 }}` + +The world is your stage, just have fun with ZK! 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. + +Check out other starters, tools, or just cool projects in the [awesome noir repository](https://github.com/noir-lang/awesome-noir). diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/explainers/cspell.json b/docs/versioned_docs/version-v1.0.0-beta.1/explainers/cspell.json new file mode 100644 index 00000000000..c60b0a597b1 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/explainers/cspell.json @@ -0,0 +1,5 @@ +{ + "words": [ + "Cryptdoku" + ] +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/explainers/explainer-oracle.md b/docs/versioned_docs/version-v1.0.0-beta.1/explainers/explainer-oracle.md new file mode 100644 index 00000000000..821e1f95c04 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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 an 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 match 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-v1.0.0-beta.1/explainers/explainer-recursion.md b/docs/versioned_docs/version-v1.0.0-beta.1/explainers/explainer-recursion.md new file mode 100644 index 00000000000..df8529ef4e0 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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.mdx), 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-v1.0.0-beta.1/explainers/explainer-writing-noir.md b/docs/versioned_docs/version-v1.0.0-beta.1/explainers/explainer-writing-noir.md new file mode 100644 index 00000000000..3ce4245dc45 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/explainers/explainer-writing-noir.md @@ -0,0 +1,177 @@ +--- +title: Thinking in Circuits +description: Considerations when writing Noir programs +keywords: [Noir, programming, rust] +tags: [Optimization] +sidebar_position: 0 +--- + + +This article intends to set you up with key concepts essential for writing more viable applications that use zero knowledge proofs, namely around efficient circuits. + +## Context - 'Efficient' is subjective + +When writing a web application for a performant computer with high-speed internet connection, writing efficient code sometimes is seen as an afterthought only if needed. Large multiplications running at the innermost of nested loops may not even be on a dev's radar. +When writing firmware for a battery-powered microcontroller, you think of cpu cycles as rations to keep within a product's power budget. + +> Code is written to create applications that perform specific tasks within specific constraints + +And these constraints differ depending on where the compiled code is execute. + +### The Ethereum Virtual Machine (EVM) + +In scenarios where extremely low gas costs are required for an Ethereum application to be viable/competitive, Ethereum smart contract developers get into what is colloquially known as: "*gas golfing*". Finding the lowest execution cost of their compiled code (EVM bytecode) to achieve a specific task. + +The equivalent optimization task when writing zk circuits is affectionately referred to as "*gate golfing*", finding the lowest gate representation of the compiled Noir code. + +### Coding for circuits - a paradigm shift + +In zero knowledge cryptography, code is compiled to "circuits" consisting of arithmetic gates, and gate count is the significant cost. Depending on the proving system this is linearly proportionate to proving time, and so from a product point this should be kept as low as possible. + +Whilst writing efficient code for web apps and Solidity has a few key differences, writing efficient circuits have a different set of considerations. It is a bit of a paradigm shift, like writing code for GPUs for the first time... + +For example, drawing a circle at (0, 0) of radius `r`: +- For a single CPU thread, +``` +for theta in 0..2*pi { + let x = r * cos(theta); + let y = r * sin(theta); + draw(x, y); +} // note: would do 0 - pi/2 and draw +ve/-ve x and y. +``` + +- For GPUs (simultaneous parallel calls with x, y across image), +``` +if (x^2 + y^2 = r^2) { + draw(x, y); +} +``` + +([Related](https://www.youtube.com/watch?v=-P28LKWTzrI)) + +Whilst this CPU -> GPU does not translate to circuits exactly, it is intended to exemplify the difference in intuition when coding for different machine capabilities/constraints. + +### Context Takeaway + +For those coming from a primarily web app background, this article will explain what you need to consider when writing circuits. Furthermore, for those experienced writing efficient machine code, prepare to shift what you think is efficient 😬 + +## Translating from Rust + +For some applications using Noir, existing code might be a convenient starting point to then proceed to optimize the gate count of. + +:::note +Many valuable functions and algorithms have been written in more established languages (C/C++), and converted to modern ones (like Rust). +::: + +Fortunately for Noir developers, when needing a particular function a Rust implementation can be readily compiled into Noir with some key changes. While the compiler does a decent amount of optimizations, it won't be able to change code that has been optimized for clock-cycles into code optimized for arithmetic gates. + +A few things to do when converting Rust code to Noir: +- `println!` is not a macro, use `println` function (same for `assert_eq`) +- No early `return` in function. Use constrain via assertion instead +- No passing by reference. Remove `&` operator to pass by value (copy) +- No boolean operators (`&&`, `||`). Use bitwise operators (`&`, `|`) with boolean values +- No type `usize`. Use types `u8`, `u32`, `u64`, ... +- `main` return must be public, `pub` +- No `const`, use `global` +- Noir's LSP is your friend, so error message should be informative enough to resolve syntax issues. + +## Writing efficient Noir for performant products + +The following points help refine our understanding over time. + +:::note +A Noir program makes a statement that can be verified. +::: + +It compiles to a structure that represents the calculation, and can assert results within the calculation at any stage (via the `constrain` keyword). + +A Noir program compiles to an Abstract Circuit Intermediate Representation which is: + - Conceptually a tree structure + - Leaves (inputs) are the `Field` type + - Nodes contain arithmetic operations to combine them (gates) + - The root is the final result (return value) + +:::tip +The command `nargo info` shows the programs circuit size, and is useful to compare the value of changes made. +You can dig deeper and use the `--print-acir` param to take a closer look at individual ACIR opcodes, and the proving backend to see its gate count (eg for barretenberg, `bb gates -b ./target/program.json`). +::: + +### Use the `Field` type + +Since the native type of values in circuits are `Field`s, using them for variables in Noir means less gates converting them under the hood. +Some things to be mindful of when using a Field type for a regular integer value: +- A variable of type `Field` can be cast `as` an integer type (eg `u8`, `u64`) + - Note: this retains only the bits of the integer type. Eg a Field value of 260 as a `u8` becomes 4 +- For Field types arithmetic operations meaningfully overflow/underflow, yet for integer types they are checked according to their size +- Comparisons and bitwise operations do not exist for `Field`s, cast to an appropriately sized integer type when you need to + +:::tip +Where possible, use `Field` type for values. Using smaller value types, and bit-packing strategies, will result in MORE gates +::: + + +### Use Arithmetic over non-arithmetic operations + +Since circuits are made of arithmetic gates, the cost of arithmetic operations tends to be one gate. Whereas for procedural code, they represent several clock cycles. + +Inversely, non-arithmetic operators are achieved with multiple gates, vs 1 clock cycle for procedural code. + +| (cost\op) | arithmetic
(`*`, `+`) | bit-wise ops
(eg `<`, `\|`, `>>`) | +| - | - | - | +| **cycles** | 10+ | 1 | +| **gates** | 1 | 10+ | + +Bit-wise operations (e.g. bit shifts `<<` and `>>`), albeit commonly used in general programming and especially for clock cycle optimizations, are on the contrary expensive in gates when performed within circuits. + +Translate away from bit shifts when writing constrained functions for the best performance. + +On the flip side, feel free to use bit shifts in unconstrained functions and tests if necessary, as they are executed outside of circuits and does not induce performance hits. + +### Use static over dynamic values + +Another general theme that manifests in different ways is that static reads are represented with less gates than dynamic ones. + +Reading from read-only memory (ROM) adds less gates than random-access memory (RAM), 2 vs ~3.25 due to the additional bounds checks. Arrays of fixed length (albeit used at a lower capacity), will generate less gates than dynamic storage. + +Related to this, if an index used to access an array is not known at compile time (ie unknown until run time), then ROM will be converted to RAM, expanding the gate count. + +:::tip +Use arrays and indices that are known at compile time where possible. +Using `assert_constant(i);` before an index, `i`, is used in an array will give a compile error if `i` is NOT known at compile time. +::: + +### Leverage unconstrained execution + +Constrained verification can leverage unconstrained execution, this is especially useful for operations that are represented by many gates. +Use an [unconstrained function](../noir/concepts/unconstrained.md) to perform gate-heavy calculations, then verify and constrain the result. + +Eg division generates more gates than multiplication, so calculating the quotient in an unconstrained function then constraining the product for the quotient and divisor (+ any remainder) equals the dividend will be more efficient. + +Use ` if is_unconstrained() { /`, to conditionally execute code if being called in an unconstrained vs constrained way. + +## Advanced + +Unless you're well into the depth of gate optimization, this advanced section can be ignored. + +### Combine arithmetic operations + +A Noir program can be honed further by combining arithmetic operators in a way that makes the most of each constraint of the backend proving system. This is in scenarios where the backend might not be doing this perfectly. + +Eg Barretenberg backend (current default for Noir) is a width-4 PLONKish constraint system +$ w_1*w_2*q_m + w_1*q_1 + w_2*q_2 + w_3*q_3 + w_4*q_4 + q_c = 0 $ + +Here we see there is one occurrence of witness 1 and 2 ($w_1$, $w_2$) being multiplied together, with addition to witnesses 1-4 ($w_1$ .. $w_4$) multiplied by 4 corresponding circuit constants ($q_1$ .. $q_4$) (plus a final circuit constant, $q_c$). + +Use `nargo info --print-acir`, to inspect the ACIR opcodes (and the proving system for gates), and it may present opportunities to amend the order of operations and reduce the number of constraints. + +#### Variable as witness vs expression + +If you've come this far and really know what you're doing at the equation level, a temporary lever (that will become unnecessary/useless over time) is: `std::as_witness`. This informs the compiler to save a variable as a witness not an expression. + +The compiler will mostly be correct and optimal, but this may help some near term edge cases that are yet to optimize. +Note: When used incorrectly it will create **less** efficient circuits (higher gate count). + +## References +- Guillaume's ["`Cryptdoku`" talk](https://www.youtube.com/watch?v=MrQyzuogxgg) (Jun'23) +- Tips from Tom, Jake and Zac. +- [Idiomatic Noir](https://www.vlayer.xyz/blog/idiomatic-noir-part-1-collections) blog post diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/getting_started/noir_installation.md b/docs/versioned_docs/version-v1.0.0-beta.1/getting_started/noir_installation.md new file mode 100644 index 00000000000..05f036d4f6d --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/getting_started/noir_installation.md @@ -0,0 +1,106 @@ +--- +title: Standalone Noir Installation +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: 2 +--- + +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](#installing-noirup). + +## Setting up shell completions + +Once `nargo` is installed, you can [set up shell completions for it](setting_up_shell_completions.md). + +## 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-v1.0.0-beta.1/getting_started/project_breakdown.md b/docs/versioned_docs/version-v1.0.0-beta.1/getting_started/project_breakdown.md new file mode 100644 index 00000000000..e442e377040 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/getting_started/project_breakdown.md @@ -0,0 +1,159 @@ +--- +title: Project Breakdown +description: + 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, proof verification, private asset transfer] +sidebar_position: 1 +--- + +This section breaks down our hello world program from the previous section. + +## Anatomy of a Nargo Project + +Upon creating a new project with `nargo new` and building the in/output files with `nargo check` +commands, you would get a minimal Nargo project of the following structure: + + - src + - Prover.toml + - 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. + +### 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) +- `expression_width` (optional) - Sets the default backend expression width. This field will override the default backend expression width specified by the Noir compiler (currently set to width 4). + +#### 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 the inputs to the Noir program (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 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)`. + +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 + +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 execution by using the `--prover-name` or `-p` flags. + +This command looks for proof inputs in the default **Prover.toml** and generates the witness and saves it at `./target/foo.gz`: + +```bash +nargo execute foo +``` + +This command looks for proof inputs in the custom **OtherProver.toml** and generates the witness and saves it at `./target/bar.gz`: + +```bash +nargo execute -p OtherProver bar +``` + +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-v1.0.0-beta.1/getting_started/quick_start.md b/docs/versioned_docs/version-v1.0.0-beta.1/getting_started/quick_start.md new file mode 100644 index 00000000000..7deeae12fd9 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/getting_started/quick_start.md @@ -0,0 +1,126 @@ +--- +title: Quick Start +tags: [] +sidebar_position: 0 +--- + +## Installation + +### Noir + +The easiest way to develop with Noir is using Nargo the CLI tool. It provides you the ability to start new projects, compile, execute and test Noir programs from the terminal. + +You can use `noirup` the installation script to quickly install and update Nargo: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/refs/heads/main/install | bash +noirup +``` + +Once installed, you can [set up shell completions for the `nargo` command](setting_up_shell_completions). + +### Proving backend + +After installing Noir, we install a proving backend to work with our Noir programs. + +Proving backends provide you the abilities to generate proofs, verify proofs, generate smart contracts and more for your Noir programs. + +Different proving backends provide different tools for working with Noir programs, here we will use the [Barretenberg proving backend](https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg) developed by Aztec Labs as an example. + +You can use the `bbup` installation script to quickly install and update BB, Barretenberg's CLI tool: + +You can find the full list of proving backends compatible with Noir in Awesome Noir. + +```bash +curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/refs/heads/master/barretenberg/bbup/install | bash +bbup +``` + +For the full list of proving backends compatible with Noir, visit [Awesome Noir](https://github.com/noir-lang/awesome-noir/?tab=readme-ov-file#proving-backends). + +## Nargo + +Nargo provides the ability to initiate and execute Noir projects. Let's initialize the traditional `hello_world`: + +```sh +nargo new hello_world +``` + +Two files will be created. + +- `src/main.nr` contains a simple boilerplate circuit +- `Nargo.toml` contains environmental options, such as name, author, dependencies, and others. + +Glancing at _main.nr_ , we can see that inputs in Noir are private by default, but can be labeled public using the keyword `pub`. This means that we will _assert_ that we know a value `x` which is different from `y` without revealing `x`: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To learn more about private and public values, check the [Data Types](../noir/concepts/data_types/index.md) section. + +### Compiling and executing + +We can now use `nargo` to generate a _Prover.toml_ file, where our input values will be specified: + +```sh +cd hello_world +nargo check + +Let's feed some valid values into this file: + +```toml +x = "1" +y = "2" +``` + +We're now ready to compile and execute our Noir program. By default the `nargo execute` command will do both, and generate the `witness` that we need to feed to our proving backend: + +```sh +nargo execute +``` + +The witness corresponding to this execution will then be written to the file _./target/witness-name.gz_. + +The command also automatically compiles your Noir program if it was not already / was edited, which you may notice the compiled artifacts being written to the file _./target/hello_world.json_. + +With circuit compiled and witness generated, we're ready to prove. + +## Proving backend + +Different proving backends may provide different tools and commands to work with Noir programs. Here Barretenberg's `bb` CLI tool is used as an example: + +```sh +bb prove -b ./target/hello_world.json -w ./target/hello_world.gz -o ./target/proof +``` + +:::tip + +Naming can be confusing, specially as you pass them to the `bb` commands. If unsure, it won't hurt to delete the target folder and start anew to make sure you're using the most recent versions of the compiled circuit and witness. + +::: + +The proof is now generated in the `target` folder. To verify it we first need to compute the verification key from the compiled circuit, and use it to verify: + +```sh +bb write_vk -b ./target/hello_world.json -o ./target/vk +bb verify -k ./target/vk -p ./target/proof +``` + +:::info + +Notice that in order to verify a proof, the verifier knows nothing but the circuit, which is compiled and used to generate the verification key. This is obviously quite important: private inputs remain private. + +As for the public inputs, you may have noticed they haven't been specified. This behavior varies with each particular backend, but barretenberg typically attaches them to the proof. You can see them by parsing and splitting it. For example for if your public inputs are 32 bytes: + +```bash +head -c 32 ./target/proof | od -An -v -t x1 | tr -d $' \n' +``` + +::: + +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-v1.0.0-beta.1/getting_started/setting_up_shell_completions.md b/docs/versioned_docs/version-v1.0.0-beta.1/getting_started/setting_up_shell_completions.md new file mode 100644 index 00000000000..0447321cbab --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/getting_started/setting_up_shell_completions.md @@ -0,0 +1,87 @@ +--- +title: Setting up shell completions +tags: [] +sidebar_position: 3 +--- + +The `nargo` binary provides a command to generate shell completions: + +```bash +nargo generate-completion-script [shell] +``` + +where `shell` must be one of `bash`, `elvish`, `fish`, `powershell`, and `zsh`. + +Below we explain how to install them in some popular shells. + +## Installing Zsh Completions + +If you have `oh-my-zsh` installed, you might already have a directory of automatically loading completion scripts — `.oh-my-zsh/completions`. +If not, first create it: + +```bash +mkdir -p ~/.oh-my-zsh/completions` +``` + +Then copy the completion script to that directory: + +```bash +nargo generate-completion-script zsh > ~/.oh-my-zsh/completions/_nargo +``` + +Without `oh-my-zsh`, you’ll need to add a path for completion scripts to your function path, and turn on completion script auto-loading. +First, add these lines to `~/.zshrc`: + +```bash +fpath=(~/.zsh/completions $fpath) +autoload -U compinit +compinit +``` + +Next, create a directory at `~/.zsh/completions`: + +```bash +mkdir -p ~/.zsh/completions +``` + +Then copy the completion script to that directory: + +```bash +nargo generate-completion-script zsh > ~/.zsh/completions/_nargo +``` + +## Installing Bash Completions + +If you have [bash-completion](https://github.com/scop/bash-completion) installed, you can just copy the completion script to the `/usr/local/etc/bash_completion.d` directory: + +```bash +nargo generate-completion-script bash > /usr/local/etc/bash_completion.d/nargo +``` + +Without `bash-completion`, you’ll need to source the completion script directly. +First create a directory such as `~/.bash_completions/`: + +```bash +mkdir ~/.bash_completions/ +``` + +Copy the completion script to that directory: + +```bash +nargo generate-completion-script bash > ~/.bash_completions/nargo.bash +``` + +Then add the following line to `~/.bash_profile` or `~/.bashrc`: + + +```bash +source ~/.bash_completions/nargo.bash +``` + +## Installing Fish Completions + +Copy the completion script to any path listed in the environment variable `$fish_completion_path`. For example, a typical location is `~/.config/fish/completions/nargo.fish`: + +```bash +nargo generate-completion-script fish > ~/.config/fish/completions/nargo.fish +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/how_to/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/how_to/debugger/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/debugger/_category_.json new file mode 100644 index 00000000000..cc2cbb1c253 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugging", + "position": 5, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/how_to/debugger/debugging_with_the_repl.md b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/debugger/debugging_with_the_repl.md new file mode 100644 index 00000000000..1d64dae3f37 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/how_to/debugger/debugging_with_vs_code.md b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/debugger/debugging_with_vs_code.md new file mode 100644 index 00000000000..8bda93324f5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/how_to/how-to-oracles.md b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/how-to-oracles.md new file mode 100644 index 00000000000..0bb8743e361 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/how-to-oracles.md @@ -0,0 +1,275 @@ +--- +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.). + +## 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 function](../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 an 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); +} + +#[test] +fn test() { + let input = [4, 16]; + main(input); +} +``` + +:::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("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; +}); +``` + +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 +export type ForeignCallSingle = string; + +export type ForeignCallArray = string[]; + +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; +``` + +:::info Multidimensional Arrays + +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../reference/nargo_commands.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 +``` + +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.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. + +:::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`? 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) => { + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(input, 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-v1.0.0-beta.1/how_to/how-to-recursion.md b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/how-to-recursion.md new file mode 100644 index 00000000000..399e4d4b38a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/how-to-recursion.md @@ -0,0 +1,172 @@ +--- +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 `bb.js`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "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.mdx), 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. + +::: + +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)`, which we want to embed in another circuit recursively. For example when proving with the `bb` tool, we can use the `--recursive` CLI option to tell the backend that it should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example of 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 UltraPlonkBackend(circuit, { threads: 8 }, { recursive: true }) +``` + +:::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) +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), + recursive: new Noir(circuits.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 { witness: recursiveWitness } = await noir_programs.recursive.execute(recursiveInputs) +const recursiveProof = await backends.recursive.generateProof(recursiveWitness); +``` + +::: diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/how_to/how-to-solidity-verifier.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/how-to-solidity-verifier.mdx new file mode 100644 index 00000000000..da36b60920d --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/how-to-solidity-verifier.mdx @@ -0,0 +1,300 @@ +--- +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 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir is universal. The witness and the compiled program can be fed into a proving backend such as Aztec's [Barretenberg](https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg), which can then generate a verifier contract for deployment on blockchains. + +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. + +Although not strictly in the domain of Noir itself, this guide shows how to generate a Solidity Verifier with Barretenberg and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You will be using Barretenberg as your proving backend +- You will be using an EVM blockchain to verify your proof +- 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/quick_start.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 with Barretenberg 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 + +:::info[Which proving system to use?] + +Barretenberg currently provides two provers: `UltraPlonk` and `UltraHonk`. In a nutshell, `UltraHonk` is faster and uses less RAM, but its verifier contract is much more expensive. `UltraPlonk` is optimized for on-chain verification, but proving is more expensive. + +In any case, we provide instructions for both. Choose your poison ☠️ + +::: + +## Step 1 - Generate a contract + +This is by far the most straightforward step. Just run: + +```sh +nargo compile +``` + +This will compile your source code into a Noir build artifact to be stored in the `./target` directory. From here on, it's Barretenberg's work. You can generate the smart contract using the commands: + + + + +```sh +bb write_vk_ultra_keccak_honk -b ./target/.json +bb contract_ultra_honk +``` + + + + +```sh +bb write_vk -b ./target/.json +bb contract +``` + + + + +replacing `` with the name of your Noir project. A `Verifier.sol` contract is now in the target folder and can be deployed to any EVM blockchain acting as a verifier smart contract. + +You can find more information about `bb` and the default Noir proving backend on [this page](../getting_started/quick_start.md#proving-backend). + + +## 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 tell you the contract is too big to deploy on mainnet, or complain about a stack too deep: + +![Contract code too big](@site/static/img/how-tos/solidity_verifier_6.png) +![Stack too deep](@site/static/img/how-tos/solidity_verifier_8.png) + +To avoid this, you can just use some optimization. Open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract ready 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 composed on multiple contracts working together. Remix will take care of the dependencies for us so we can simply deploy the Verifier contract by selecting it and hitting "deploy": + + + + +![Deploying HonkVerifier](@site/static/img/how-tos/solidity_verifier_7.png) + + + + +![Deploying PlonkVerifier](@site/static/img/how-tos/solidity_verifier_9.png) + + + + +A contract will show up in the "Deployed Contracts" section. + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +First generate a proof with `bb`. We need a `Prover.toml` file for our inputs. Run: + +```bash +nargo check +``` + +This will generate a `Prover.toml` you can fill with the values you want to prove. We can now execute the circuit with `nargo` and then use the proving backend to prove: + + + + +```bash +nargo execute +bb prove_ultra_keccak_honk -b ./target/.json -w ./target/ -o ./target/proof +``` + +:::tip[Public inputs] +Barretenberg attaches the public inputs to the proof, which in this case it's not very useful. If you're up for some JS, `bb.js` has [a method for it](https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/ts/src/proof/index.ts), but in the CLI you can use this ugly snippet: + +```bash +cat ./target/proof | od -An -v -t x1 | tr -d $' \n' | sed 's/^.\{8\}//' | (read hex; echo "${hex:0:192}${hex:256}") +``` + +Beautiful. This assumes a circuit with one public input (32 bytes, for Barretenberg). For more inputs, you can just increment `hex:256` with 32 more bytes for each public input. + +::: + + + + +```bash +nargo execute +bb prove -b ./target/.json -w ./target/ -o ./target/proof +``` + + +:::tip[Public inputs] +Barretenberg attaches the public inputs to the proof, which in this case it's not very useful. If you're up for some JS, `bb.js` has [a method for it](https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/ts/src/proof/index.ts), but in the CLI you can use this ugly snippet: + +```bash +tail -c +33 ./target/proof | od -An -v -t x1 | tr -d $' \n' +``` + +Beautiful. This assumes a circuit with one public input (32 bytes, for Barretenberg). For more inputs, you can just add 32 more bytes for each public input to the `tail` command. + +::: + + + + +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): + +```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. + +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 + +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: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo +- BSC +- Blast L2 +- Avalanche C-Chain +- Mode +- Linea +- Moonbeam + +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-v1.0.0-beta.1/how_to/merkle-proof.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..0a128adb2de --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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] +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 + +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-v1.0.0-beta.1/how_to/using-devcontainers.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/index.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/index.mdx new file mode 100644 index 00000000000..5c116a73b3f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/index.mdx @@ -0,0 +1,76 @@ +--- +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'; +import ThemedImage from '@theme/ThemedImage'; +import useBaseUrl from '@docusaurus/useBaseUrl'; + + + +Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of statements without revealing all inputs to the statements. You can read more about Zero-Knowledge Proofs [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-v1.0.0-beta.1/migration_notes.md b/docs/versioned_docs/version-v1.0.0-beta.1/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/assert.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/assert.md new file mode 100644 index 00000000000..2132de42072 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/assert.md @@ -0,0 +1,78 @@ +--- +title: Assert Function +description: + Learn about the `assert` and `static_assert` functions 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 or compile-time, respectively. +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); +``` + +There is also a special `static_assert` function that behaves like `assert`, +but that runs at compile-time. + +```rust +fn main(xs: [Field; 3]) { + let x = 2 + 2; + let y = 4; + static_assert(x == y, "expected 2 + 2 to equal 4"); + + // This passes since the length of `xs` is known at compile-time + static_assert(xs.len() == 3, "expected the input to have 3 elements"); +} +``` + +This function fails when passed a dynamic (run-time) argument: + +```rust +fn main(x : Field, y : Field) { + // this fails because `x` is not known at compile-time + static_assert(x == 2, "expected x to be known at compile-time and equal to 2"); + + let mut example_slice = &[]; + if y == 4 { + example_slice = example_slice.push_back(0); + } + + // This fails because the length of `example_slice` is not known at + // compile-time + let error_message = "expected an empty slice, known at compile-time"; + static_assert(example_slice.len() == 0, error_message); +} +``` + diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/comments.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/comptime.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/comptime.md new file mode 100644 index 00000000000..353d6dbc681 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/comptime.md @@ -0,0 +1,565 @@ +--- +title: Compile-time Code & Metaprogramming +description: Learn how to use metaprogramming in Noir to create macros or derive your own traits +keywords: [Noir, comptime, compile-time, metaprogramming, macros, quote, unquote] +sidebar_position: 15 +--- + +## Overview + +Metaprogramming in Noir is comprised of three parts: +1. `comptime` code +2. Quoting and unquoting +3. The metaprogramming API in `std::meta` + +Each of these are explained in more detail in the next sections but the wide picture is that +`comptime` allows us to write code which runs at compile-time. In this `comptime` code we +can quote and unquote snippets of the program, manipulate them, and insert them in other +parts of the program. Comptime functions which do this are said to be macros. Additionally, +there's a compile-time API of built-in types and functions provided by the compiler which allows +for greater analysis and modification of programs. + +--- + +## Comptime + +`comptime` is a new keyword in Noir which marks an item as executing or existing at compile-time. It can be used in several ways: + +- `comptime fn` to define functions which execute exclusively during compile-time. +- `comptime global` to define a global variable which is evaluated at compile-time. + - Unlike runtime globals, `comptime global`s can be mutable. +- `comptime { ... }` to execute a block of statements during compile-time. +- `comptime let` to define a variable whose value is evaluated at compile-time. +- `comptime for` to run a for loop at compile-time. Syntax sugar for `comptime { for .. }`. + +### Scoping + +Note that while in a `comptime` context, any runtime variables _local to the current function_ are never visible. + +### Evaluating + +Evaluation rules of `comptime` follows the normal unconstrained evaluation rules for other Noir code. There are a few things to note though: + +- Certain built-in functions may not be available, although more may be added over time. +- Evaluation order of `comptime {}` blocks within global items is currently unspecified. For example, given the following two functions we can't guarantee +which `println` will execute first. The ordering of the two printouts will be arbitrary, but should be stable across multiple compilations with the same `nargo` version as long as the program is also unchanged. + +```rust +fn one() { + comptime { println("one"); } +} + +fn two() { + comptime { println("two"); } +} +``` + +- Since evaluation order is unspecified, care should be taken when using mutable globals so that they do not rely on a particular ordering. +For example, using globals to generate unique ids should be fine but relying on certain ids always being produced (especially after edits to the program) should be avoided. +- Although the ordering of comptime code is usually unspecified, there are cases where it is: + - Dependencies of a crate will always be evaluated before the dependent crate. + - Any attributes on a function will be run before the function body is resolved. This is to allow the attribute to modify the function if necessary. Note that if the + function itself was called at compile-time previously, it will already be resolved and cannot be modified. To prevent accidentally calling functions you wish to modify + at compile-time, it may be helpful to sort your `comptime` annotation functions into a different submodule crate along with any dependencies they require. + - Unlike raw `comptime {}` blocks, attributes on top-level items in the program do have a set evaluation order. Attributes within a module are evaluated top-down, and attributes + in different modules are evaluated submodule-first. Sibling modules to the same parent module are evaluated in order of the module declarations (`mod foo; mod bar;`) in their + parent module. + +### Lowering + +When a `comptime` value is used in runtime code it must be lowered into a runtime value. This means replacing the expression with the literal that it evaluated to. For example, the code: + +```rust +struct Foo { array: [Field; 2], len: u32 } + +fn main() { + println(comptime { + let mut foo = std::mem::zeroed::(); + foo.array[0] = 4; + foo.len = 1; + foo + }); +} +``` + +will be converted to the following after `comptime` expressions are evaluated: + +```rust +struct Foo { array: [Field; 2], len: u32 } + +fn main() { + println(Foo { array: [4, 0], len: 1 }); +} +``` + +Not all types of values can be lowered. For example, references, `Type`s, and `TypeDefinition`s (among other types) cannot be lowered at all. + +```rust +fn main() { + // There's nothing we could inline here to create a Type value at runtime + // let _ = get_type!(); +} + +comptime fn get_type() -> Type { ... } +``` + +Values of certain types may also change type when they are lowered. For example, a comptime format string will already be +formatted, and thus lowers into a runtime string instead: + +```rust +fn main() { + let foo = comptime { + let i = 2; + f"i = {i}" + }; + assert_eq(foo, "i = 2"); +} +``` + +--- + +## (Quasi) Quote + +Macros in Noir are `comptime` functions which return code as a value which is inserted into the call site when it is lowered there. +A code value in this case is of type `Quoted` and can be created by a `quote { ... }` expression. +More specifically, the code value `quote` creates is a token stream - a representation of source code as a series of words, numbers, string literals, or operators. +For example, the expression `quote { Hi "there reader"! }` would quote three tokens: the word "hi", the string "there reader", and an exclamation mark. +You'll note that snippets that would otherwise be invalid syntax can still be quoted. + +When a `Quoted` value is used in runtime code, it is lowered into a `quote { ... }` expression. Since this expression is only valid +in compile-time code however, we'd get an error if we tried this. Instead, we can use macro insertion to insert each token into the +program at that point, and parse it as an expression. To do this, we have to add a `!` after the function name returning the `Quoted` value. +If the value was created locally and there is no function returning it, `std::meta::unquote!(_)` can be used instead. +Calling such a function at compile-time without `!` will just return the `Quoted` value to be further manipulated. For example: + +```rust title="quote-example" showLineNumbers +comptime fn quote_one() -> Quoted { + quote { 1 } + } + + #[test] + fn returning_versus_macro_insertion() { + comptime { + // let _a: Quoted = quote { 1 }; + let _a: Quoted = quote_one(); + + // let _b: Field = 1; + let _b: Field = quote_one!(); + + // Since integers default to fields, if we + // want a different type we have to explicitly cast + // let _c: i32 = 1 as i32; + let _c: i32 = quote_one!() as i32; + } + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L120-L140 + + +For those familiar with quoting from other languages (primarily lisps), Noir's `quote` is actually a _quasiquote_. +This means we can escape the quoting by using the unquote operator to splice values in the middle of quoted code. + +In addition to curly braces, you can also use square braces for the quote operator: + +```rust +comptime { + let q1 = quote { 1 }; + let q2 = quote [ 2 ]; + assert_eq(q1, q2); + + // Square braces can be used to quote mismatched curly braces if needed + let _ = quote[}]; +} +``` + +--- + +## Unquote + +The unquote operator `$` is usable within a `quote` expression. +It takes a variable as an argument, evaluates the variable, and splices the resulting value into the quoted token stream at that point. For example, + +```rust +comptime { + let x = 1 + 2; + let y = quote { $x + 4 }; +} +``` + +The value of `y` above will be the token stream containing `3`, `+`, and `4`. We can also use this to combine `Quoted` values into larger token streams: + +```rust +comptime { + let x = quote { 1 + 2 }; + let y = quote { $x + 4 }; +} +``` + +The value of `y` above is now the token stream containing five tokens: `1 + 2 + 4`. + +Note that to unquote something, a variable name _must_ follow the `$` operator in a token stream. +If it is an expression (even a parenthesized one), it will do nothing. Most likely a parse error will be given when the macro is later unquoted. + +Unquoting can also be avoided by escaping the `$` with a backslash: + +```rust +comptime { + let x = quote { 1 + 2 }; + + // y contains the four tokens: `$x + 4` + let y = quote { \$x + 4 }; +} +``` + +### Combining Tokens + +Note that `Quoted` is internally a series of separate tokens, and that all unquoting does is combine these token vectors. +This means that code which appears to append like a string actually appends like a vector internally: + +```rust +comptime { + let x = 3; + let q = quote { foo$x }; // This is [foo, 3], not [foo3] + + // Spaces are ignored in general, they're never part of a token + assert_eq(q, quote { foo 3 }); +} +``` + +If you do want string semantics, you can use format strings then convert back to a `Quoted` value with `.quoted_contents()`. +Note that formatting a quoted value with multiple tokens will always insert a space between each token. If this is +undesired, you'll need to only operate on quoted values containing a single token. To do this, you can iterate +over each token of a larger quoted value with `.tokens()`: + +```rust title="concatenate-example" showLineNumbers +comptime fn concatenate(q1: Quoted, q2: Quoted) -> Quoted { + assert(q1.tokens().len() <= 1); + assert(q2.tokens().len() <= 1); + + f"{q1}{q2}".quoted_contents() + } + + // The CtString type is also useful for a compile-time string of unbounded size + // so that you can append to it in a loop. + comptime fn double_spaced(q: Quoted) -> CtString { + let mut result = "".as_ctstring(); + + for token in q.tokens() { + if result != "".as_ctstring() { + result = result.append_str(" "); + } + result = result.append_fmtstr(f"{token}"); + } + + result + } + + #[test] + fn concatenate_test() { + comptime { + let result = concatenate(quote {foo}, quote {bar}); + assert_eq(result, quote {foobar}); + + let result = double_spaced(quote {foo bar 3}).as_quoted_str!(); + assert_eq(result, "foo bar 3"); + } + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L255-L288 + + +--- + +## Attributes + +Attributes provide a way to run a `comptime` function on an item in the program. +When you use an attribute, the function with the same name will be called with that item as an argument: + +```rust +#[my_struct_attribute] +struct Foo {} + +comptime fn my_struct_attribute(s: StructDefinition) { + println("Called my_struct_attribute!"); +} + +#[my_function_attribute] +fn foo() {} + +comptime fn my_function_attribute(f: FunctionDefinition) { + println("Called my_function_attribute!"); +} +``` + +Anything returned from one of these functions will be inserted at top-level along with the original item. +Note that expressions are not valid at top-level so you'll get an error trying to return `3` or similar just as if you tried to write a program containing `3; struct Foo {}`. +You can insert other top-level items such as trait impls, structs, or functions this way though. +For example, this is the mechanism used to insert additional trait implementations into the program when deriving a trait impl from a struct: + +```rust title="derive-field-count-example" showLineNumbers +trait FieldCount { + fn field_count() -> u32; + } + + #[derive_field_count] + struct Bar { + x: Field, + y: [Field; 2], + } + + comptime fn derive_field_count(s: StructDefinition) -> Quoted { + let typ = s.as_type(); + let field_count = s.fields().len(); + quote { + impl FieldCount for $typ { + fn field_count() -> u32 { + $field_count + } + } + } + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L142-L164 + + +### Calling annotations with additional arguments + +Arguments may optionally be given to attributes. +When this is done, these additional arguments are passed to the attribute function after the item argument. + +```rust title="annotation-arguments-example" showLineNumbers +#[assert_field_is_type(quote { i32 }.as_type())] + struct MyStruct { + my_field: i32, + } + + comptime fn assert_field_is_type(s: StructDefinition, typ: Type) { + // Assert the first field in `s` has type `typ` + let fields = s.fields(); + assert_eq(fields[0].1, typ); + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L166-L177 + + +We can also take any number of arguments by adding the `varargs` attribute: + +```rust title="annotation-varargs-example" showLineNumbers +#[assert_three_args(1, 2, 3)] + struct MyOtherStruct { + my_other_field: u32, + } + + #[varargs] + comptime fn assert_three_args(_s: StructDefinition, args: [Field]) { + assert_eq(args.len(), 3); + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L179-L189 + + +### Attribute Evaluation Order + +Unlike the evaluation order of stray `comptime {}` blocks within functions, attributes have a well-defined evaluation +order. Within a module, attributes are evaluated top to bottom. Between modules, attributes in child modules are evaluated +first. Attributes in sibling modules are resolved following the `mod foo; mod bar;` declaration order within their parent +modules. + +```rust +mod foo; // attributes in foo are run first +mod bar; // followed by attributes in bar + +// followed by any attributes in the parent module +#[derive(Eq)] +struct Baz {} +``` + +Note that because of this evaluation order, you may get an error trying to derive a trait for a struct whose fields +have not yet had the trait derived already: + +```rust +// Error! `Bar` field of `Foo` does not (yet) implement Eq! +#[derive(Eq)] +struct Foo { + bar: Bar +} + +#[derive(Eq)] +struct Bar {} +``` + +In this case, the issue can be resolved by rearranging the structs. + +--- + +## Comptime API + +Although `comptime`, `quote`, and unquoting provide a flexible base for writing macros, +Noir's true metaprogramming ability comes from being able to interact with the compiler through a compile-time API. +This API can be accessed through built-in functions in `std::meta` as well as on methods of several `comptime` types. + +The following is an incomplete list of some `comptime` types along with some useful methods on them. You can see more in the standard library [Metaprogramming section](../standard_library/meta). + +- `Quoted`: A token stream +- `Type`: The type of a Noir type + - `fn implements(self, constraint: TraitConstraint) -> bool` + - Returns true if `self` implements the given trait constraint +- `Expr`: A syntactically valid expression. Can be used to recur on a program's parse tree to inspect how it is structured. + - Methods: + - `fn as_function_call(self) -> Option<(Expr, [Expr])>` + - If this is a function call expression, return `(function, arguments)` + - `fn as_block(self) -> Option<[Expr]>` + - If this is a block, return each statement in the block +- `FunctionDefinition`: A function definition + - Methods: + - `fn parameters(self) -> [(Quoted, Type)]` + - Returns a slice of `(name, type)` pairs for each parameter +- `StructDefinition`: A struct definition + - Methods: + - `fn as_type(self) -> Type` + - Returns this `StructDefinition` as a `Type`. Any generics are kept as-is + - `fn generics(self) -> [Quoted]` + - Return the name of each generic on this struct + - `fn fields(self) -> [(Quoted, Type)]` + - Return the name and type of each field +- `TraitConstraint`: A trait constraint such as `From` +- `TypedExpr`: A type-checked expression. +- `UnresolvedType`: A syntactic notation that refers to a Noir type that hasn't been resolved yet + +There are many more functions available by exploring the `std::meta` module and its submodules. +Using these methods is the key to writing powerful metaprogramming libraries. + +### `#[use_callers_scope]` + +Since certain functions such as `Quoted::as_type`, `Expression::as_type`, or `Quoted::as_trait_constraint` will attempt +to resolve their contents in a particular scope - it can be useful to change the scope they resolve in. By default +these functions will resolve in the current function's scope which is usually the attribute function they are called in. +If you're working on a library however, this may be a completely different module or crate to the item you're trying to +use the attribute on. If you want to be able to use `Quoted::as_type` to refer to types local to the caller's scope for +example, you can annotate your attribute function with `#[use_callers_scope]`. This will ensure your attribute, and any +closures it uses, can refer to anything in the caller's scope. `#[use_callers_scope]` also works recursively. So if both +your attribute function and a helper function it calls use it, then they can both refer to the same original caller. + +--- + +## Example: Derive + +Using all of the above, we can write a `derive` macro that behaves similarly to Rust's but is not built into the language. +From the user's perspective it will look like this: + +```rust +// Example usage +#[derive(Default, Eq, Ord)] +struct MyStruct { my_field: u32 } +``` + +To implement `derive` we'll have to create a `comptime` function that accepts +a variable amount of traits. + +```rust title="derive_example" showLineNumbers +// These are needed for the unconstrained hashmap we're using to store derive functions +use crate::collections::umap::UHashMap; +use crate::hash::BuildHasherDefault; +use crate::hash::poseidon2::Poseidon2Hasher; + +// A derive function is one that given a struct definition can +// create us a quoted trait impl from it. +pub type DeriveFunction = fn(StructDefinition) -> Quoted; + +// We'll keep a global HANDLERS map to keep track of the derive handler for each trait +comptime mut global HANDLERS: UHashMap> = + UHashMap::default(); + +// Given a struct and a slice of traits to derive, create trait impls for each. +// This function is as simple as iterating over the slice, checking if we have a trait +// handler registered for the given trait, calling it, and appending the result. +#[varargs] +pub comptime fn derive(s: StructDefinition, traits: [TraitDefinition]) -> Quoted { + let mut result = quote {}; + + for trait_to_derive in traits { + let handler = HANDLERS.get(trait_to_derive); + assert(handler.is_some(), f"No derive function registered for `{trait_to_derive}`"); + + let trait_impl = handler.unwrap()(s); + result = quote { $result $trait_impl }; + } + + result +} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L31-L64 + + +Registering a derive function could be done as follows: + +```rust title="derive_via" showLineNumbers +// To register a handler for a trait, just add it to our handlers map +pub comptime fn derive_via(t: TraitDefinition, f: DeriveFunction) { + HANDLERS.insert(t, f); +} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L66-L73 + + +```rust title="big-derive-usage-example" showLineNumbers +// Finally, to register a handler we call the above function as an annotation + // with our handler function. + #[derive_via(derive_do_nothing)] + trait DoNothing { + fn do_nothing(self); + } + + comptime fn derive_do_nothing(s: StructDefinition) -> Quoted { + // This is simplified since we don't handle generics or where clauses! + // In a real example we'd likely also need to introduce each of + // `s.generics()` as well as a trait constraint for each generic + // to ensure they also implement the trait. + let typ = s.as_type(); + quote { + impl DoNothing for $typ { + fn do_nothing(self) { + // Traits can't tell us what to do + println("something"); + } + } + } + } + + // Since `DoNothing` is a simple trait which: + // 1. Only has one method + // 2. Does not have any generics on the trait itself + // We can use `std::meta::make_trait_impl` to help us out. + // This helper function will generate our impl for us along with any + // necessary where clauses and still provides a flexible interface + // for us to work on each field on the struct. + comptime fn derive_do_nothing_alt(s: StructDefinition) -> Quoted { + let trait_name = quote { DoNothing }; + let method_signature = quote { fn do_nothing(self) }; + + // Call `do_nothing` recursively on each field in the struct + let for_each_field = |field_name| quote { self.$field_name.do_nothing(); }; + + // Some traits like Eq want to join each field expression with something like `&`. + // We don't need that here + let join_fields_with = quote {}; + + // The body function is a spot to insert any extra setup/teardown needed. + // We'll insert our println here. Since we recur on each field, we should see + // one println for the struct itself, followed by a println for every field (recursively). + let body = |body| quote { + println("something"); + $body + }; + crate::meta::make_trait_impl( + s, + trait_name, + method_signature, + for_each_field, + join_fields_with, + body, + ) + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L191-L249 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/control_flow.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/control_flow.md new file mode 100644 index 00000000000..b365bb22728 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/control_flow.md @@ -0,0 +1,79 @@ +--- +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 +} +``` + +Alternatively, `start..=end` can be used for a range that is inclusive on both ends. + +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-v1.0.0-beta.1/noir/concepts/data_bus.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_bus.mdx new file mode 100644 index 00000000000..e55e58622ce --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_bus.mdx @@ -0,0 +1,23 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +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-v1.0.0-beta.1/noir/concepts/data_types/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/arrays.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..289145a8c4d --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/arrays.md @@ -0,0 +1,276 @@ +--- +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.mdx), 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. The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument. + +Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements. + +```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 the starting element. + +Requires `self` to be non-empty. + +```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); +} +``` + +### as_str_unchecked + +Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation - +the given array is interpreted as-is as a string. + +```rust +impl [u8; N] { + pub fn as_str_unchecked(self) -> str +} +``` + +example: + +```rust +fn main() { + let hi = [104, 105].as_str_unchecked(); + assert_eq(hi, "hi"); +} +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/booleans.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..2507af710e7 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/booleans.md @@ -0,0 +1,28 @@ +--- +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; +} +``` + +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.md) and +[Assert Function](../assert.md) sections. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/fields.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..6739d6500dd --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/fields.md @@ -0,0 +1,246 @@ +--- +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 title="to_le_bits" showLineNumbers +pub fn to_le_bits(self: Self) -> [u1; N] {} +``` +> Source code: noir_stdlib/src/field/mod.nr#L32-L34 + + +example: + +```rust title="to_le_bits_example" showLineNumbers +fn test_to_le_bits() { + let field = 2; + let bits: [u1; 8] = field.to_le_bits(); + assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L277-L283 + + + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust title="to_be_bits" showLineNumbers +pub fn to_be_bits(self: Self) -> [u1; N] {} +``` +> Source code: noir_stdlib/src/field/mod.nr#L48-L50 + + +example: + +```rust title="to_be_bits_example" showLineNumbers +fn test_to_be_bits() { + let field = 2; + let bits: [u1; 8] = field.to_be_bits(); + assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L268-L274 + + + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust title="to_le_bytes" showLineNumbers +pub fn to_le_bytes(self: Self) -> [u8; N] { +``` +> Source code: noir_stdlib/src/field/mod.nr#L61-L63 + + +example: + +```rust title="to_le_bytes_example" showLineNumbers +fn test_to_le_bytes() { + let field = 2; + let bytes: [u8; 8] = field.to_le_bytes(); + assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]); + assert_eq(Field::from_le_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L296-L303 + + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust title="to_be_bytes" showLineNumbers +pub fn to_be_bytes(self: Self) -> [u8; N] { +``` +> Source code: noir_stdlib/src/field/mod.nr#L94-L96 + + +example: + +```rust title="to_be_bytes_example" showLineNumbers +fn test_to_be_bytes() { + let field = 2; + let bytes: [u8; 8] = field.to_be_bytes(); + assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]); + assert_eq(Field::from_be_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L286-L293 + + + +### to_le_radix + +Decomposes into an array over the specified base, Little Endian + +```rust title="to_le_radix" showLineNumbers +pub fn to_le_radix(self: Self, radix: u32) -> [u8; N] { + // Brillig does not need an immediate radix + if !crate::runtime::is_unconstrained() { + crate::assert_constant(radix); + } + self.__to_le_radix(radix) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L118-L126 + + + +example: + +```rust title="to_le_radix_example" showLineNumbers +fn test_to_le_radix() { + let field = 2; + let bytes: [u8; 8] = field.to_le_radix(256); + assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]); + assert_eq(Field::from_le_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L316-L323 + + + +### to_be_radix + +Decomposes into an array over the specified base, Big Endian + +```rust title="to_be_radix" showLineNumbers +pub fn to_be_radix(self: Self, radix: u32) -> [u8; N] { + // Brillig does not need an immediate radix + if !crate::runtime::is_unconstrained() { + crate::assert_constant(radix); + } + self.__to_be_radix(radix) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L128-L136 + + +example: + +```rust title="to_be_radix_example" showLineNumbers +fn test_to_be_radix() { + let field = 2; + let bytes: [u8; 8] = field.to_be_radix(256); + assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]); + assert_eq(Field::from_be_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L306-L313 + + + +### 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 title="assert_max_bit_size" showLineNumbers +pub fn assert_max_bit_size(self) { +``` +> Source code: noir_stdlib/src/field/mod.nr#L10-L12 + + +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-v1.0.0-beta.1/noir/concepts/data_types/function_types.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/data_types/index.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..0f2db2b2d75 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/index.md @@ -0,0 +1,126 @@ +--- +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 +``` + +By default, like functions, type aliases are private to the module they exist in. You can use `pub` +to make the type alias public or `pub(crate)` to make it public to just its crate: + +```rust +// This type alias is now public +pub type Id = u8; +``` + +## Wildcard Type +Noir can usually infer the type of the variable from the context, so specifying the type of a variable is only required when it cannot be inferred. However, specifying a complex type can be tedious, especially when it has multiple generic arguments. Often some of the generic types can be inferred from the context, and Noir only needs a hint to properly infer the other types. We can partially specify a variable's type by using `_` as a marker, indicating where we still want the compiler to infer the type. + +```rust +let a: [_; 4] = foo(b); +``` + + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/integers.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..41a823646dd --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/integers.md @@ -0,0 +1,167 @@ +--- +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\\$). + + +```rust +fn main(x: i16, y: i16) { + // modulo + let c = x % y; + let c = x % -13; +} +``` + +Modulo operation is defined for negative integers thanks to integer division, so that the equality `x = (x/y)*y + (x%y)` holds. + +## 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 z = 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 execute +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 + +fn main(x: u8, y: u8) -> pub u8 { + std::wrapping_add(x, y) +} +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/references.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/data_types/slices.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..cfee564a302 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/slices.mdx @@ -0,0 +1,358 @@ +--- +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 +fn main() -> pub u32 { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +To write a slice literal, use a preceding 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]); +} +``` + +### map + +Applies a function to each element of the slice, returning a new slice containing the mapped elements. + +```rust +fn map(self, f: fn[Env](T) -> U) -> [U] +``` + +example + +```rust +let a = &[1, 2, 3]; +let b = a.map(|a| a * 2); // b is now &[2, 4, 6] +``` + +### fold + +Applies a function to each element of the slice, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the slice, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = &[1]; +let a2 = &[1, 2]; +let a3 = &[1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let folded = slice.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as the starting element. + +```rust +fn reduce(self, f: fn[Env](T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let reduced = slice.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### filter + +Returns a new slice containing only elements for which the given predicate returns true. + +```rust +fn filter(self, f: fn[Env](T) -> bool) -> Self +``` + +example: + +```rust +fn main() { + let slice = &[1, 2, 3, 4, 5]; + let odds = slice.filter(|x| x % 2 == 1); + assert_eq(odds, &[1, 3, 5]); +} +``` + +### join + +Flatten each element in the slice into one value, separated by `separator`. + +Note that although slices implement `Append`, `join` cannot be used on slice +elements since nested slices are prohibited. + +```rust +fn join(self, separator: T) -> T where T: Append +``` + +example: + +```rust +struct Accumulator { + total: Field, +} + +// "Append" two accumulators by adding them +impl Append for Accumulator { + fn empty() -> Self { + Self { total: 0 } + } + + fn append(self, other: Self) -> Self { + Self { total: self.total + other.total } + } +} + +fn main() { + let slice = &[1, 2, 3, 4, 5].map(|total| Accumulator { total }); + + let result = slice.join(Accumulator::empty()); + assert_eq(result, Accumulator { total: 15 }); + + // We can use a non-empty separator to insert additional elements to sum: + let separator = Accumulator { total: 10 }; + let result = slice.join(separator); + assert_eq(result, Accumulator { total: 55 }); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(self, predicate: fn[Env](T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let all = slice.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 5]; + let any = slice.any(|a| a == 5); + assert(any); +} + +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/strings.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..b2257e8bdbb --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/strings.md @@ -0,0 +1,114 @@ +--- +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.md). + +```rust + +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."#####; +``` + +## Format strings + +A format string begins with the letter `f` and allows inserting the value of local and global variables in it. + +Example: + +```rust +let four = 2 + 2; +let s = f"Two plus two is: {four}"; +println(s); +``` + +The output of the above program is: + +```text +Two plus two is: 4 +``` + +To insert the value of a local or global variable, put it inside `{...}` in the string. + +If you need to write the `{` or `}` characters, use `{{` and `}}` respectively: + +```rust +let four = 2 + 2; + +// Prints "This is not expanded: {four}" +println(f"This is not expanded: {{four}}"); +``` + +More complex expressions are not allowed inside `{...}`: + +```rust +let s = f"Two plus two is: {2 + 2}" // Error: invalid format string +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/structs.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..29951ae843a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/structs.md @@ -0,0 +1,96 @@ +--- +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. + +### Visibility + +By default, like functions, structs are private to the module they exist in. You can use `pub` +to make the struct public or `pub(crate)` to make it public to just its crate: + +```rust +// This struct is now public +pub struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +The same applies to struct fields: by default they are private to the module they exist in, +but they can be made `pub` or `pub(crate)`: + +```rust +// This struct is now public +pub struct Animal { + hands: Field, // private to its module + pub(crate) legs: Field, // accessible from the entire crate + pub eyes: u8, // accessible from anywhere +} +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/tuples.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/functions.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/functions.md new file mode 100644 index 00000000000..f656cdfd97a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/generics.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/generics.md new file mode 100644 index 00000000000..c180a0ce7e6 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/generics.md @@ -0,0 +1,251 @@ +--- +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 +} +``` + +## Numeric Generics + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks similar to using regular generics, but introducing them into scope +requires declaring them with `let MyGenericName: IntegerType`. This can be done anywhere a normal +generic is declared. Instead of types, these generics resolve to integers at compile-time. +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 + } +} +``` + +## 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. + +## 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.md) 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.md). + +## Manually Specifying Generics with the Turbofish Operator + +There are times when the compiler cannot reasonably infer what type should be used for a generic, or when the developer themselves may want to manually distinguish generic type parameters. This is where the `::<>` turbofish operator comes into play. + +The `::<>` operator can follow a variable or path and can be used to manually specify generic arguments within the angle brackets. +The name "turbofish" comes from that `::<>` looks like a little fish. + +Examples: +```rust +fn main() { + let mut slice = []; + slice = slice.push_back(1); + slice = slice.push_back(2); + // Without turbofish a type annotation would be needed on the left hand side + let array = slice.as_array::<2>(); +} +``` + + +```rust +trait MyTrait { + fn ten() -> Self; +} + +impl MyTrait for Field { + fn ten() -> Self { 10 } +} + +struct Foo { + inner: T +} + +impl Foo { + fn generic_method(_self: Self) -> U where U: MyTrait { + U::ten() + } +} + +fn example() { + let foo: Foo = Foo { inner: 1 }; + // Using a type other than `Field` here (e.g. u32) would fail as + // there is no matching impl for `u32: MyTrait`. + // + // Substituting the `10` on the left hand side of this assert + // with `10 as u32` would also fail with a type mismatch as we + // are expecting a `Field` from the right hand side. + assert(10 as u32 == foo.generic_method::()); +} +``` + +## Arithmetic Generics + +In addition to numeric generics, Noir also allows a limited form of arithmetic on generics. +When you have a numeric generic such as `N`, you can use the following operators on it in a +type position: `+`, `-`, `*`, `/`, and `%`. + +Note that type checking arithmetic generics is a best effort guess from the compiler and there +are many cases of types that are equal that the compiler may not see as such. For example, +we know that `T * (N + M)` should be equal to `T*N + T*M` but the compiler does not currently +apply the distributive law and thus sees these as different types. + +Even with this limitation though, the compiler can handle common cases decently well: + +```rust +trait Serialize { + fn serialize(self) -> [Field; N]; +} + +impl Serialize<1> for Field { + fn serialize(self) -> [Field; 1] { + [self] + } +} + +impl Serialize for [T; N] + where T: Serialize { .. } + +impl Serialize for (T, U) + where T: Serialize, U: Serialize { .. } + +fn main() { + let data = (1, [2, 3, 4]); + assert_eq(data.serialize().len(), 4); +} +``` + +Note that if there is any over or underflow the types will fail to unify: + +```rust title="underflow-example" showLineNumbers +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn main() { + // error: Could not determine array length `(0 - 1)` + pop([]); +} +``` +> Source code: test_programs/compile_failure/arithmetic_generics_underflow/src/main.nr#L1-L14 + + +This also applies if there is underflow in an intermediate calculation: + +```rust title="intermediate-underflow-example" showLineNumbers +fn main() { + // From main it looks like there's nothing sketchy going on + seems_fine([]); +} + +// Since `seems_fine` says it can receive and return any length N +fn seems_fine(array: [Field; N]) -> [Field; N] { + // But inside `seems_fine` we pop from the array which + // requires the length to be greater than zero. + + // error: Could not determine array length `(0 - 1)` + push_zero(pop(array)) +} + +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn push_zero(array: [Field; N]) -> [Field; N + 1] { + let mut result: [Field; N + 1] = std::mem::zeroed(); + for i in 0..N { + result[i] = array[i]; + } + // index N is already zeroed + result +} +``` +> Source code: test_programs/compile_failure/arithmetic_generics_intermediate_underflow/src/main.nr#L1-L32 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/globals.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/globals.md new file mode 100644 index 00000000000..c64b6c53746 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/globals.md @@ -0,0 +1,82 @@ +--- +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 must be specified by the user: + +```rust +global N: Field = 5; + +global TUPLE: (Field, Field) = (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: u32 = 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: u32 = 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: Field = 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: [Field; 100] = 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. + +### Visibility + +By default, like functions, globals are private to the module they exist in. You can use `pub` +to make the global public or `pub(crate)` to make it public to just its crate: + +```rust +// This global is now public +pub global N: u32 = 5; +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/lambdas.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/mutability.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/ops.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/ops.md new file mode 100644 index 00000000000..c35c36c38a9 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/oracles.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/oracles.mdx new file mode 100644 index 00000000000..77a2ac1550a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/oracles.mdx @@ -0,0 +1,29 @@ +--- +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 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +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-v1.0.0-beta.1/noir/concepts/shadowing.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/concepts/traits.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/traits.md new file mode 100644 index 00000000000..b6c0a886eb0 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/traits.md @@ -0,0 +1,584 @@ +--- +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 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; let N: u32] 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 + } +} +``` + +Where clauses can also be placed on struct implementations. +For example, here is a method utilizing a generic type that implements the equality trait. + +```rust +struct Foo { + a: u32, + b: T, +} + +impl Foo where T: Eq { + fn eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.eq(other.b) + } +} +``` + +## 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); +} +``` + +### Associated Types and Constants + +Traits also support associated types and constraints which can be thought of as additional generics that are referred to by name. + +Here's an example of a trait with an associated type `Foo` and a constant `Bar`: + +```rust +trait MyTrait { + type Foo; + + let Bar: u32; +} +``` + +Now when we're implementing `MyTrait` we also have to provide values for `Foo` and `Bar`: + +```rust +impl MyTrait for Field { + type Foo = i32; + + let Bar: u32 = 11; +} +``` + +Since associated constants can also be used in a type position, its values are limited to only other +expression kinds allowed in numeric generics. + +Note that currently all associated types and constants must be explicitly specified in a trait constraint. +If we leave out any, we'll get an error that we're missing one: + +```rust +// Error! Constraint is missing associated constant for `Bar` +fn foo(x: T) where T: MyTrait { + ... +} +``` + +Because all associated types and constants must be explicitly specified, they are essentially named generics, +although this is set to change in the future. Future versions of Noir will allow users to elide associated types +in trait constraints similar to Rust. When this is done, you may still refer to their value with the `::AssociatedType` +syntax: + +```rust +// Only valid in future versions of Noir: +fn foo(x: T) where T: MyTrait { + let _: ::Foo = ...; +} +``` + +The type as trait syntax is possible in Noir today but is less useful when each type must be explicitly specified anyway: + +```rust +fn foo(x: T) where T: MyTrait { + // Works, but could just use F directly + let _: >::Foo = ...; + + let _: F = ...; +} +``` + +## 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: some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: 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. + +### Trait Inheritance + +Sometimes, you might need one trait to use another trait’s functionality (like "inheritance" in some other languages). In this case, you can specify this relationship by listing any child traits after the parent trait's name and a colon. Now, whenever the parent trait is implemented it will require the child traits to be implemented as well. A parent trait is also called a "super trait." + +```rust +trait Person { + fn name(self) -> String; +} + +// Person is a supertrait of Student. +// Implementing Student requires you to also impl Person. +trait Student: Person { + fn university(self) -> String; +} + +trait Programmer { + fn fav_language(self) -> String; +} + +// CompSciStudent (computer science student) is a subtrait of both Programmer +// and Student. Implementing CompSciStudent requires you to impl both supertraits. +trait CompSciStudent: Programmer + Student { + fn git_username(self) -> String; +} +``` + +### Trait Aliases + +Similar to the proposed Rust feature for [trait aliases](https://github.com/rust-lang/rust/blob/4d215e2426d52ca8d1af166d5f6b5e172afbff67/src/doc/unstable-book/src/language-features/trait-alias.md), +Noir supports aliasing one or more traits and using those aliases wherever +traits would normally be used. + +```rust +trait Foo { + fn foo(self) -> Self; +} + +trait Bar { + fn bar(self) -> Self; +} + +// Equivalent to: +// trait Baz: Foo + Bar {} +// +// impl Baz for T where T: Foo + Bar {} +trait Baz = Foo + Bar; + +// We can use `Baz` to refer to `Foo + Bar` +fn baz(x: T) -> T where T: Baz { + x.foo().bar() +} +``` + +#### Generic Trait Aliases + +Trait aliases can also be generic by placing the generic arguments after the +trait name. These generics are in scope of every item within the trait alias. + +```rust +trait Foo { + fn foo(self) -> Self; +} + +trait Bar { + fn bar(self) -> T; +} + +// Equivalent to: +// trait Baz: Foo + Bar {} +// +// impl Baz for U where U: Foo + Bar {} +trait Baz = Foo + Bar; +``` + +#### Trait Alias Where Clauses + +Trait aliases support where clauses to add trait constraints to any of their +generic arguments, e.g. ensuring `T: Baz` for a trait alias `Qux`. + +```rust +trait Foo { + fn foo(self) -> Self; +} + +trait Bar { + fn bar(self) -> T; +} + +trait Baz { + fn baz(self) -> bool; +} + +// Equivalent to: +// trait Qux: Foo + Bar where T: Baz {} +// +// impl Qux for U where +// U: Foo + Bar, +// T: Baz, +// {} +trait Qux = Foo + Bar where T: Baz; +``` + +Note that while trait aliases support where clauses, +the equivalent traits can fail due to [#6467](https://github.com/noir-lang/noir/issues/6467) + +### Visibility + +By default, like functions, traits and trait aliases are private to the module +they exist in. You can use `pub` to make the trait public or `pub(crate)` to make +it public to just its crate: + +```rust +// This trait is now public +pub trait Trait {} + +// This trait alias is now public +pub trait Baz = Foo + Bar; +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/unconstrained.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..8e07d719f4b --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/unconstrained.md @@ -0,0 +1,106 @@ +--- +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 = unsafe { + //@safety: 'out' is properly constrained below in 'assert(num == reconstructed_num);' + 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). + +Note that in order to invoke unconstrained functions we need to wrap them in an `unsafe` block, +to make it clear that the call is unconstrained. +Furthermore, a warning is emitted unless the `unsafe` block starts with a `//@safety: ...` comment explaining why it is fine to call the unconstrained function. + +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.md#break-and-continue) diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..22186b22598 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,122 @@ +--- +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 ecrecover; +use lib_a; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use std::hash::sha256; +use std::scalar_mul::fixed_base_embedded_curve; +``` + +Lastly, You can import multiple items in the same line by enclosing them in curly braces: + +```rust +use std::hash::{keccak256, sha256}; +``` + +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) 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 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-v1.0.0-beta.1/noir/modules_packages_crates/modules.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..14aa1f0579a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/modules.md @@ -0,0 +1,221 @@ +--- +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 + +``` + +The module filename may also be the name of the module as a directory with the contents in a +file named `mod.nr` within that directory. The above example can alternatively be expressed like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +fn from_foo() {} +``` + +Note that it's an error to have both files `src/foo.nr` and `src/foo/mod.nr` in the filesystem. + +### 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 +``` + +Similar to importing a module in the crate root, modules can be placed in a `mod.nr` file, like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar/mod.nr` + +```rust +fn from_bar() {} +``` + +### Referencing a parent module + +Given a submodule, you can refer to its parent module using the `super` keyword. + +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 +// Same as bar::from_foo +use super::from_foo; + +fn from_bar() { + from_foo(); // invokes super::from_foo(), which is bar::from_foo() + super::from_foo(); // also invokes bar::from_foo() +} +``` + +### `use` visibility + +`use` declarations are private to the containing module, by default. However, like functions, +they can be marked as `pub` or `pub(crate)`. Such a use declaration serves to _re-export_ a name. +A public `use` declaration can therefore redirect some public name to a different target definition: +even a definition with a private canonical path, inside a different module. + +An example of re-exporting: + +```rust +mod some_module { + pub use foo::{bar, baz}; + mod foo { + pub fn bar() {} + pub fn baz() {} + } +} + +fn main() { + some_module::bar(); + some_module::baz(); +} +``` + +In this example, the module `some_module` re-exports two public names defined in `foo`. + +### Visibility + +By default, like functions, modules are private to the module (or crate) they exist in. You can use `pub` +to make the module public or `pub(crate)` to make it public to just its crate: + +```rust +// This module is now public and can be seen by other crates. +pub mod foo; +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..2fbf10aec52 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,46 @@ +--- +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. The `--package` option can be used to limit +the scope of some commands to a specific member of the workspace; otherwise these commands run on the package nearest on the path to the +current directory where `nargo` was invoked. + +`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. + +Please note that nesting regular packages is not supported: certain commands work on the workspace level and will use the topmost Nargo.toml file they can find on the path; unless this is a workspace configuration with `members`, the command might run on some unintended package. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/standard_library/bigint.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/bigint.md new file mode 100644 index 00000000000..2743739e8b1 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/bigint.md @@ -0,0 +1,127 @@ +--- +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. + +:::note + +`nargo` can be built with `--profile release-pedantic` to enable extra overflow checks which may affect `BigInt` results in some cases. +Consider the [`noir-bignum`](https://github.com/noir-lang/noir-bignum) library for an optimized alternative approach. + +::: + +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 +pub struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L28-L33 + + +## 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#L75-L83 + + +## 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-v1.0.0-beta.1/noir/standard_library/black_box_fns.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..e9392b20a92 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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: + +- [AES128](./cryptographic_primitives/ciphers.mdx#aes128) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [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.mdx) + +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-v1.0.0-beta.1/noir/standard_library/bn254.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/standard_library/containers/boundedvec.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..dad25f26717 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,479 @@ +--- +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 good() -> 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 `good`'s return value + v2 +} + +fn bad() { + // Error: Type annotation needed + // The compiler can't infer `MaxLen` from this code. + let mut v3 = BoundedVec::new(); + 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(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(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 + + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to 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); + assert(first != 42); + v.set(0, 42); + let new_first = v.get(0); + assert(new_first == 42); +} +``` + +### set_unchecked + +```rust +pub fn set_unchecked(&mut self: Self, index: u64, value: T) -> T { +``` + +Writes an element to 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="set_unchecked_example" showLineNumbers +fn set_unchecked_example() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2]); + + // Here we're safely writing within the valid range of `vec` + // `vec` now has the value [42, 2] + vec.set_unchecked(0, 42); + + // We can then safely read this value back out of `vec`. + // Notice that we use the checked version of `get` which would prevent reading unsafe values. + assert_eq(vec.get(0), 42); + + // We've now written past the end of `vec`. + // As this index is still within the maximum potential length of `v`, + // it won't cause a constraint failure. + vec.set_unchecked(2, 42); + println(vec); + + // This will write past the end of the maximum potential length of `vec`, + // it will then trigger a constraint failure. + vec.set_unchecked(5, 42); + println(vec); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L67-L91 + + + +### 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#L95-L103 + + +### 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#L108-L120 + + +### 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#L125-L140 + + +### 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#L145-L151 + + +### 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#L156-L163 + + +### 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#L168-L175 + + +### 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#L180-L189 + + +### 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]) +``` + +### from_parts + +```rust +pub fn from_parts(mut array: [T; MaxLen], len: u32) -> Self +``` + +Creates a new BoundedVec from the given array and length. +The given length must be less than or equal to the length of the array. + +This function will zero out any elements at or past index `len` of `array`. +This incurs an extra runtime cost of O(MaxLen). If you are sure your array is +zeroed after that index, you can use `from_parts_unchecked` to remove the extra loop. + +Example: + +```rust title="from-parts" showLineNumbers +let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3); + assert_eq(vec.len(), 3); + + // Any elements past the given length are zeroed out, so these + // two vectors will be completely equal + let vec1: BoundedVec = BoundedVec::from_parts([1, 2, 3, 1], 3); + let vec2: BoundedVec = BoundedVec::from_parts([1, 2, 3, 2], 3); + assert_eq(vec1, vec2); +``` +> Source code: noir_stdlib/src/collections/bounded_vec.nr#L663-L672 + + +### from_parts_unchecked + +```rust +pub fn from_parts_unchecked(array: [T; MaxLen], len: u32) -> Self +``` + +Creates a new BoundedVec from the given array and length. +The given length must be less than or equal to the length of the array. + +This function is unsafe because it expects all elements past the `len` index +of `array` to be zeroed, but does not check for this internally. Use `from_parts` +for a safe version of this function which does zero out any indices past the +given length. Invalidating this assumption can notably cause `BoundedVec::eq` +to give incorrect results since it will check even elements past `len`. + +Example: + +```rust title="from-parts-unchecked" showLineNumbers +let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3); + assert_eq(vec.len(), 3); + + // invalid use! + let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3); + let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3); + + // both vectors have length 3 so we'd expect them to be equal, but this + // fails because elements past the length are still checked in eq + assert(vec1 != vec2); +``` +> Source code: noir_stdlib/src/collections/bounded_vec.nr#L677-L688 + + +### map + +```rust +pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec +``` + +Creates a new vector of equal size by calling a closure on each element in this vector. + +Example: + +```rust title="bounded-vec-map-example" showLineNumbers +let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| value * 2); +``` +> Source code: noir_stdlib/src/collections/bounded_vec.nr#L551-L554 + + +### 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#L256-L262 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/containers/hashmap.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..810baad16ba --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/containers/hashmap.md @@ -0,0 +1,587 @@ +--- +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`. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a poseidon2 hasher +use 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, +{ + /// Constructs an empty HashMap. + /// + /// Example: + /// + /// ```noir + /// let hashmap: HashMap> = HashMap::default(); + /// assert(hashmap.is_empty()); + /// ``` + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L688-L703 + + +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#L208-L211 + + +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#L202-L204 + + +### 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#L103-L108 + + +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#L212-L217 + + +### 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#L472-L479 + + +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#L297-L305 + + +### 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#L514-L521 + + +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#L218-L222 + + +### 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#L570-L577 + + +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#L225-L232 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L167-L169 + + +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#L233-L241 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L431-L433 + + +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#L242-L257 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L453-L455 + + +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#L258-L263 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +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#L264-L268 + + +### 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#L143-L150 + + +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#L191-L193 + + +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#L308-L319 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L230-L232 + + +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#L320-L330 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L267-L269 + + +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#L331-L340 + + +### 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#L304-L311 + + +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#L344-L347 + + +### 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#L342-L349 + + +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#L348-L351 + + +### 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#L374-L376 + + +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#L352-L355 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L395-L397 + + +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#L280-L282 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default, +{ + /// Constructs an empty HashMap. + /// + /// Example: + /// + /// ```noir + /// let hashmap: HashMap> = HashMap::default(); + /// assert(hashmap.is_empty()); + /// ``` + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L688-L703 + + +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#L208-L211 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher, +{ + /// Checks if two HashMaps are equal. + /// + /// Example: + /// + /// ```noir + /// 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); + /// ``` + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L636-L661 + + +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#L283-L294 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/containers/index.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/standard_library/containers/vec.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..475011922f8 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/containers/vec.mdx @@ -0,0 +1,170 @@ +--- +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); +``` + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +Panics if the index points beyond the vector's end. + +Example: + +```rust +let vector: Vec = Vec::from_slice(&[10, 20, 30]); +assert(vector.get(1) == 20); +vector.set(1, 42); +assert(vector.get(1) == 42); +``` + +### 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-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/ciphers.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/ciphers.mdx new file mode 100644 index 00000000000..d6a5e1a79eb --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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'; + +## 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-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..8d96027b42c --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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'; + +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-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx new file mode 100644 index 00000000000..482a36932b9 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx @@ -0,0 +1,95 @@ +--- +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'; + +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: [EmbeddedCurvePoint; N], + scalars: [EmbeddedCurveScalar; N], +) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L103-L108 + + +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: EmbeddedCurveScalar) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L120-L122 + + +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 +pub fn embedded_curve_add( + point1: EmbeddedCurvePoint, + point2: EmbeddedCurvePoint, +) -> EmbeddedCurvePoint { +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L136-L141 + + +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-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/hashes.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..e010d6d85c2 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,227 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s and pedersen +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox'; + +## 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]) -> HASH +``` +> Source code: noir_stdlib/src/hash/sha256.nr#L47-L49 + + +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#L15-L17 + + +```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/mod.nr#L18-L20 + + +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/mod.nr#L24-L26 + + +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/mod.nr#L49-L51 + + +example: + +```rust title="pedersen-hash" showLineNumbers +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-L6 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { +``` +> Source code: noir_stdlib/src/hash/mod.nr#L29-L31 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +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); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L7 + + + + +## 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/mod.nr#L119-L121 + + +example: + +```rust title="keccak256" showLineNumbers +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-L20 + + + + +## 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 std::hash::poseidon; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L11 + + +## 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); +``` + +example: + +```rust title="poseidon2" showLineNumbers +use std::hash::poseidon2; + +fn main(inputs: [Field; 4], expected_hash: Field) { + let hash = poseidon2::Poseidon2::hash(inputs, inputs.len()); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/poseidon2/src/main.nr#L1-L8 + + +## 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-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/index.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/standard_library/fmtstr.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/fmtstr.md new file mode 100644 index 00000000000..19809d60261 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/fmtstr.md @@ -0,0 +1,17 @@ +--- +title: fmtstr +--- + +`fmtstr` is the type resulting from using format string (`f"..."`). + +## Methods + +### quoted_contents + +```rust title="quoted_contents" showLineNumbers +pub comptime fn quoted_contents(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/format_string.nr#L3-L5 + + +Returns the format string contents (that is, without the leading and trailing double quotes) as a `Quoted` value. \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/is_unconstrained.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/is_unconstrained.md new file mode 100644 index 00000000000..51bb1bda8f1 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/is_unconstrained.md @@ -0,0 +1,69 @@ +--- +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. + +Note that using `is_unconstrained` in a `comptime` context will also return `true`: + +``` +fn main() { + comptime { + assert(is_unconstrained()); + } +} +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/logging.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/standard_library/mem.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/mem.md new file mode 100644 index 00000000000..1e9102b32dc --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/mem.md @@ -0,0 +1,82 @@ +--- +title: Memory Module +description: + This module contains functions which manipulate memory in a low-level way +keywords: + [ + mem, memory, zeroed, transmute, checked_transmute + ] +--- + +# `std::mem::zeroed` + +```rust +fn zeroed() -> T +``` + +Returns 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. + +This function currently supports the following types: + +- Field +- Bool +- Uint +- Array +- Slice +- String +- Tuple +- Functions + +Using it on other types could result in unexpected behavior. + +# `std::mem::checked_transmute` + +```rust +fn checked_transmute(value: T) -> U +``` + +Transmutes a value of one type into the same value but with a new type `U`. + +This function is safe to use since both types are asserted to be equal later during compilation after the concrete values for generic types become known. +This function is useful for cases where the compiler may fail a type check that is expected to pass where +a user knows the two types to be equal. For example, when using arithmetic generics there are cases the compiler +does not see as equal, such as `[Field; N*(A + B)]` and `[Field; N*A + N*B]`, which users may know to be equal. +In these cases, `checked_transmute` can be used to cast the value to the desired type while also preserving safety +by checking this equality once `N`, `A`, `B` are fully resolved. + +Note that since this safety check is performed after type checking rather than during, no error is issued if the function +containing `checked_transmute` is never called. + +# `std::mem::array_refcount` + +```rust +fn array_refcount(array: [T; N]) -> u32 {} +``` + +Returns the internal reference count of an array value in unconstrained code. + +Arrays only have reference count in unconstrained code - using this anywhere +else will return zero. + +This function is mostly intended for debugging compiler optimizations but can also be used +to find where array copies may be happening in unconstrained code by placing it before array +mutations. + +# `std::mem::slice_refcount` + +```rust +fn slice_refcount(slice: [T]) -> u32 {} +``` + +Returns the internal reference count of a slice value in unconstrained code. + +Slices only have reference count in unconstrained code - using this anywhere +else will return zero. + +This function is mostly intended for debugging compiler optimizations but can also be used +to find where slice copies may be happening in unconstrained code by placing it before slice +mutations. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/merkle_trees.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..6a9ebf72ada --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/standard_library/meta/ctstring.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/ctstring.md new file mode 100644 index 00000000000..b76f873ca03 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/ctstring.md @@ -0,0 +1,100 @@ +--- +title: CtString +--- + +`std::meta::ctstring` contains methods on the built-in `CtString` type which is +a compile-time, dynamically-sized string type. Compared to `str` and `fmtstr`, +`CtString` is useful because its size does not need to be specified in its type. This +can be used for formatting items at compile-time or general string handling in `comptime` +code. + +Since `fmtstr`s can be converted into `CtString`s, you can make use of their formatting +abilities in CtStrings by formatting in `fmtstr`s then converting the result to a CtString +afterward. + +## Traits + +### AsCtString + +```rust title="as-ctstring" showLineNumbers +pub trait AsCtString { + comptime fn as_ctstring(self) -> CtString; +} +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L43-L47 + + +Converts an object into a compile-time string. + +Implementations: + +```rust +impl AsCtString for str { ... } +impl AsCtString for fmtstr { ... } +``` + +## Methods + +### new + +```rust title="new" showLineNumbers +pub comptime fn new() -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L4-L6 + + +Creates an empty `CtString`. + +### append_str + +```rust title="append_str" showLineNumbers +pub comptime fn append_str(self, s: str) -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L11-L13 + + +Returns a new CtString with the given str appended onto the end. + +### append_fmtstr + +```rust title="append_fmtstr" showLineNumbers +pub comptime fn append_fmtstr(self, s: fmtstr) -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L17-L19 + + +Returns a new CtString with the given fmtstr appended onto the end. + +### as_quoted_str + +```rust title="as_quoted_str" showLineNumbers +pub comptime fn as_quoted_str(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L26-L28 + + +Returns a quoted string literal from this string's contents. + +There is no direct conversion from a `CtString` to a `str` since +the size would not be known. To get around this, this function can +be used in combination with macro insertion (`!`) to insert this string +literal at this function's call site. + +Example: + +```rust title="as_quoted_str_example" showLineNumbers +let my_ctstring = "foo bar".as_ctstring(); + let my_str = my_ctstring.as_quoted_str!(); + + assert_eq(crate::meta::type_of(my_str), quote { str<7> }.as_type()); +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L92-L97 + + +## Trait Implementations + +```rust +impl Eq for CtString +impl Hash for CtString +impl Append for CtString +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/expr.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/expr.md new file mode 100644 index 00000000000..b6d395c6700 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/expr.md @@ -0,0 +1,380 @@ +--- +title: Expr +--- + +`std::meta::expr` contains methods on the built-in `Expr` type for quoted, syntactically valid expressions. + +## Methods + +### as_array + +```rust title="as_array" showLineNumbers +pub comptime fn as_array(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L10-L12 + + +If this expression is an array, this returns a slice of each element in the array. + +### as_assert + +```rust title="as_assert" showLineNumbers +pub comptime fn as_assert(self) -> Option<(Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L16-L18 + + +If this expression is an assert, this returns the assert expression and the optional message. + +### as_assert_eq + +```rust title="as_assert_eq" showLineNumbers +pub comptime fn as_assert_eq(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L23-L25 + + +If this expression is an assert_eq, this returns the left-hand-side and right-hand-side +expressions, together with the optional message. + +### as_assign + +```rust title="as_assign" showLineNumbers +pub comptime fn as_assign(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L30-L32 + + +If this expression is an assignment, this returns a tuple with the left hand side +and right hand side in order. + +### as_binary_op + +```rust title="as_binary_op" showLineNumbers +pub comptime fn as_binary_op(self) -> Option<(Expr, BinaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L37-L39 + + +If this expression is a binary operator operation ` `, +return the left-hand side, operator, and the right-hand side of the operation. + +### as_block + +```rust title="as_block" showLineNumbers +pub comptime fn as_block(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L44-L46 + + +If this expression is a block `{ stmt1; stmt2; ...; stmtN }`, return +a slice containing each statement. + +### as_bool + +```rust title="as_bool" showLineNumbers +pub comptime fn as_bool(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L50-L52 + + +If this expression is a boolean literal, return that literal. + +### as_cast + +```rust title="as_cast" showLineNumbers +#[builtin(expr_as_cast)] + pub comptime fn as_cast(self) -> Option<(Expr, UnresolvedType)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L56-L59 + + +If this expression is a cast expression (`expr as type`), returns the casted +expression and the type to cast to. + +### as_comptime + +```rust title="as_comptime" showLineNumbers +pub comptime fn as_comptime(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L64-L66 + + +If this expression is a `comptime { stmt1; stmt2; ...; stmtN }` block, +return each statement in the block. + +### as_constructor + +```rust title="as_constructor" showLineNumbers +pub comptime fn as_constructor(self) -> Option<(UnresolvedType, [(Quoted, Expr)])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L71-L73 + + +If this expression is a constructor `Type { field1: expr1, ..., fieldN: exprN }`, +return the type and the fields. + +### as_for + +```rust title="as_for" showLineNumbers +pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L78-L80 + + +If this expression is a for statement over a single expression, return the identifier, +the expression and the for loop body. + +### as_for_range + +```rust title="as_for" showLineNumbers +pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L78-L80 + + +If this expression is a for statement over a range, return the identifier, +the range start, the range end and the for loop body. + +### as_function_call + +```rust title="as_function_call" showLineNumbers +pub comptime fn as_function_call(self) -> Option<(Expr, [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L92-L94 + + +If this expression is a function call `foo(arg1, ..., argN)`, return +the function and a slice of each argument. + +### as_if + +```rust title="as_if" showLineNumbers +pub comptime fn as_if(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L100-L102 + + +If this expression is an `if condition { then_branch } else { else_branch }`, +return the condition, then branch, and else branch. If there is no else branch, +`None` is returned for that branch instead. + +### as_index + +```rust title="as_index" showLineNumbers +pub comptime fn as_index(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L107-L109 + + +If this expression is an index into an array `array[index]`, return the +array and the index. + +### as_integer + +```rust title="as_integer" showLineNumbers +pub comptime fn as_integer(self) -> Option<(Field, bool)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L114-L116 + + +If this expression is an integer literal, return the integer as a field +as well as whether the integer is negative (true) or not (false). + +### as_lambda + +```rust title="as_lambda" showLineNumbers +pub comptime fn as_lambda( + self, + ) -> Option<([(Expr, Option)], Option, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L120-L124 + + +If this expression is a lambda, returns the parameters, return type and body. + +### as_let + +```rust title="as_let" showLineNumbers +pub comptime fn as_let(self) -> Option<(Expr, Option, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L129-L131 + + +If this expression is a let statement, returns the let pattern as an `Expr`, +the optional type annotation, and the assigned expression. + +### as_member_access + +```rust title="as_member_access" showLineNumbers +pub comptime fn as_member_access(self) -> Option<(Expr, Quoted)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L136-L138 + + +If this expression is a member access `foo.bar`, return the struct/tuple +expression and the field. The field will be represented as a quoted value. + +### as_method_call + +```rust title="as_method_call" showLineNumbers +pub comptime fn as_method_call(self) -> Option<(Expr, Quoted, [UnresolvedType], [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L143-L145 + + +If this expression is a method call `foo.bar::(arg1, ..., argN)`, return +the receiver, method name, a slice of each generic argument, and a slice of each argument. + +### as_repeated_element_array + +```rust title="as_repeated_element_array" showLineNumbers +pub comptime fn as_repeated_element_array(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L150-L152 + + +If this expression is a repeated element array `[elem; length]`, return +the repeated element and the length expressions. + +### as_repeated_element_slice + +```rust title="as_repeated_element_slice" showLineNumbers +pub comptime fn as_repeated_element_slice(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L157-L159 + + +If this expression is a repeated element slice `[elem; length]`, return +the repeated element and the length expressions. + +### as_slice + +```rust title="as_slice" showLineNumbers +pub comptime fn as_slice(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L164-L166 + + +If this expression is a slice literal `&[elem1, ..., elemN]`, +return each element of the slice. + +### as_tuple + +```rust title="as_tuple" showLineNumbers +pub comptime fn as_tuple(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L171-L173 + + +If this expression is a tuple `(field1, ..., fieldN)`, +return each element of the tuple. + +### as_unary_op + +```rust title="as_unary_op" showLineNumbers +pub comptime fn as_unary_op(self) -> Option<(UnaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L178-L180 + + +If this expression is a unary operation ` `, +return the unary operator as well as the right-hand side expression. + +### as_unsafe + +```rust title="as_unsafe" showLineNumbers +pub comptime fn as_unsafe(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L185-L187 + + +If this expression is an `unsafe { stmt1; ...; stmtN }` block, +return each statement inside in a slice. + +### has_semicolon + +```rust title="has_semicolon" showLineNumbers +pub comptime fn has_semicolon(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L206-L208 + + +`true` if this expression is trailed by a semicolon. E.g. + +``` +comptime { + let expr1 = quote { 1 + 2 }.as_expr().unwrap(); + let expr2 = quote { 1 + 2; }.as_expr().unwrap(); + + assert(expr1.as_binary_op().is_some()); + assert(expr2.as_binary_op().is_some()); + + assert(!expr1.has_semicolon()); + assert(expr2.has_semicolon()); +} +``` + +### is_break + +```rust title="is_break" showLineNumbers +pub comptime fn is_break(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L212-L214 + + +`true` if this expression is `break`. + +### is_continue + +```rust title="is_continue" showLineNumbers +pub comptime fn is_continue(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L218-L220 + + +`true` if this expression is `continue`. + +### modify + +```rust title="modify" showLineNumbers +pub comptime fn modify(self, f: fn[Env](Expr) -> Option) -> Expr { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L229-L231 + + +Applies a mapping function to this expression and to all of its sub-expressions. +`f` will be applied to each sub-expression first, then applied to the expression itself. + +This happens recursively for every expression within `self`. + +For example, calling `modify` on `(&[1], &[2, 3])` with an `f` that returns `Option::some` +for expressions that are integers, doubling them, would return `(&[2], &[4, 6])`. + +### quoted + +```rust title="quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L266-L268 + + +Returns this expression as a `Quoted` value. It's the same as `quote { $self }`. + +### resolve + +```rust title="resolve" showLineNumbers +pub comptime fn resolve(self, in_function: Option) -> TypedExpr {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L282-L284 + + +Resolves and type-checks this expression and returns the result as a `TypedExpr`. + +The `in_function` argument specifies where the expression is resolved: +- If it's `none`, the expression is resolved in the function where `resolve` was called +- If it's `some`, the expression is resolved in the given function + +If any names used by this expression are not in scope or if there are any type errors, +this will give compiler errors as if the expression was written directly into +the current `comptime` function. \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/function_def.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/function_def.md new file mode 100644 index 00000000000..b7f2ebdb889 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/function_def.md @@ -0,0 +1,166 @@ +--- +title: FunctionDefinition +--- + +`std::meta::function_def` contains methods on the built-in `FunctionDefinition` type representing +a function definition in the source program. + +## Methods + +### add_attribute + +```rust title="add_attribute" showLineNumbers +pub comptime fn add_attribute(self, attribute: str) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L3-L5 + + +Adds an attribute to the function. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### body + +```rust title="body" showLineNumbers +pub comptime fn body(self) -> Expr {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L8-L10 + + +Returns the body of the function as an expression. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +pub comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L13-L15 + + +Returns true if this function has a custom attribute with the given name. + +### is_unconstrained + +```rust title="is_unconstrained" showLineNumbers +pub comptime fn is_unconstrained(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L18-L20 + + +Returns true if this function is unconstrained. + +### module + +```rust title="module" showLineNumbers +pub comptime fn module(self) -> Module {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L23-L25 + + +Returns the module where the function is defined. + +### name + +```rust title="name" showLineNumbers +pub comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L28-L30 + + +Returns the name of the function. + +### parameters + +```rust title="parameters" showLineNumbers +pub comptime fn parameters(self) -> [(Quoted, Type)] {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L33-L35 + + +Returns each parameter of the function as a tuple of (parameter pattern, parameter type). + +### return_type + +```rust title="return_type" showLineNumbers +pub comptime fn return_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L38-L40 + + +The return type of the function. + +### set_body + +```rust title="set_body" showLineNumbers +pub comptime fn set_body(self, body: Expr) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L43-L45 + + +Mutate the function body to a new expression. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_parameters + +```rust title="set_parameters" showLineNumbers +pub comptime fn set_parameters(self, parameters: [(Quoted, Type)]) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L48-L50 + + +Mutates the function's parameters to a new set of parameters. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +Expects a slice of (parameter pattern, parameter type) for each parameter. Requires +each parameter pattern to be a syntactically valid parameter. + +### set_return_type + +```rust title="set_return_type" showLineNumbers +pub comptime fn set_return_type(self, return_type: Type) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L53-L55 + + +Mutates the function's return type to a new type. This is only valid +on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_return_public + +```rust title="set_return_public" showLineNumbers +pub comptime fn set_return_public(self, public: bool) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L58-L60 + + +Mutates the function's return visibility to public (if `true` is given) or private (if `false` is given). +This is only valid on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +### set_unconstrained + +```rust title="set_unconstrained" showLineNumbers +pub comptime fn set_unconstrained(self, value: bool) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L66-L68 + + +Mutates the function to be unconstrained (if `true` is given) or not (if `false` is given). +This is only valid on functions in the current crate which have not yet been resolved. +This means any functions called at compile-time are invalid targets for this method. + +## Trait Implementations + +```rust +impl Eq for FunctionDefinition +impl Hash for FunctionDefinition +``` + +Note that each function is assigned a unique ID internally and this is what is used for +equality and hashing. So even functions with identical signatures and bodies may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/index.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/index.md new file mode 100644 index 00000000000..132f4c0216e --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/index.md @@ -0,0 +1,224 @@ +--- +title: Metaprogramming +description: Noir's Metaprogramming API +keywords: [metaprogramming, comptime, macros, macro, quote, unquote] +--- + +`std::meta` is the entry point for Noir's metaprogramming API. This consists of `comptime` functions +and types used for inspecting and modifying Noir programs. + +## Functions + +### type_of + +```rust title="type_of" showLineNumbers +pub comptime fn type_of(x: T) -> Type {} +``` +> Source code: noir_stdlib/src/meta/mod.nr#L27-L29 + + +Returns the type of a variable at compile-time. + +Example: +```rust +comptime { + let x: i32 = 1; + let x_type: Type = std::meta::type_of(x); + + assert_eq(x_type, quote { i32 }.as_type()); +} +``` + +### unquote + +```rust title="unquote" showLineNumbers +pub comptime fn unquote(code: Quoted) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L19-L21 + + +Unquotes the passed-in token stream where this function was called. + +Example: +```rust +comptime { + let code = quote { 1 + 2 }; + + // let x = 1 + 2; + let x = unquote!(code); +} +``` + +### derive + +```rust title="derive" showLineNumbers +#[varargs] +pub comptime fn derive(s: StructDefinition, traits: [TraitDefinition]) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L48-L51 + + +Attribute placed on struct definitions. + +Creates a trait impl for each trait passed in as an argument. +To do this, the trait must have a derive handler registered +with `derive_via` beforehand. The traits in the stdlib that +can be derived this way are `Eq`, `Ord`, `Default`, and `Hash`. + +Example: +```rust +#[derive(Eq, Default)] +struct Foo { + x: i32, + y: T, +} + +fn main() { + let foo1 = Foo::default(); + let foo2 = Foo { x: 0, y: &[0] }; + assert_eq(foo1, foo2); +} +``` + +### derive_via + +```rust title="derive_via_signature" showLineNumbers +pub comptime fn derive_via(t: TraitDefinition, f: DeriveFunction) { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L68-L70 + + +Attribute placed on trait definitions. + +Registers a function to create impls for the given trait +when the trait is used in a `derive` call. Users may use +this to register their own functions to enable their traits +to be derived by `derive`. + +Because this function requires a function as an argument which +should produce a trait impl for any given struct, users may find +it helpful to use a function like `std::meta::make_trait_impl` to +help creating these impls. + +Example: +```rust +#[derive_via(derive_do_nothing)] +trait DoNothing { + fn do_nothing(self); +} + +comptime fn derive_do_nothing(s: StructDefinition) -> Quoted { + let typ = s.as_type(); + quote { + impl DoNothing for $typ { + fn do_nothing(self) { + println("Nothing"); + } + } + } +} +``` + +As another example, `derive_eq` in the stdlib is used to derive the `Eq` +trait for any struct. It makes use of `make_trait_impl` to do this: + +```rust title="derive_eq" showLineNumbers +comptime fn derive_eq(s: StructDefinition) -> Quoted { + let signature = quote { fn eq(_self: Self, _other: Self) -> bool }; + let for_each_field = |name| quote { (_self.$name == _other.$name) }; + let body = |fields| { + if s.fields().len() == 0 { + quote { true } + } else { + fields + } + }; + crate::meta::make_trait_impl( + s, + quote { Eq }, + signature, + for_each_field, + quote { & }, + body, + ) +} +``` +> Source code: noir_stdlib/src/cmp.nr#L10-L30 + + +### make_trait_impl + +```rust title="make_trait_impl" showLineNumbers +pub comptime fn make_trait_impl( + s: StructDefinition, + trait_name: Quoted, + function_signature: Quoted, + for_each_field: fn[Env1](Quoted) -> Quoted, + join_fields_with: Quoted, + body: fn[Env2](Quoted) -> Quoted, +) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/mod.nr#L87-L96 + + +A helper function to more easily create trait impls while deriving traits. + +Note that this function only works for traits which: +1. Have only one method +2. Have no generics on the trait itself. + - E.g. Using this on a trait such as `trait Foo { ... }` will result in the + generated impl incorrectly missing the `T` generic. + +If your trait fits these criteria then `make_trait_impl` is likely the easiest +way to write your derive handler. The arguments are as follows: + +- `s`: The struct to make the impl for +- `trait_name`: The name of the trait to derive. E.g. `quote { Eq }`. +- `function_signature`: The signature of the trait method to derive. E.g. `fn eq(self, other: Self) -> bool`. +- `for_each_field`: An operation to be performed on each field. E.g. `|name| quote { (self.$name == other.$name) }`. +- `join_fields_with`: A separator to join each result of `for_each_field` with. + E.g. `quote { & }`. You can also use an empty `quote {}` for no separator. +- `body`: The result of the field operations is passed into this function for any final processing. + This is the place to insert any setup/teardown code the trait requires. If the trait doesn't require + any such code, you can return the body as-is: `|body| body`. + +Example deriving `Hash`: + +```rust title="derive_hash" showLineNumbers +comptime fn derive_hash(s: StructDefinition) -> Quoted { + let name = quote { Hash }; + let signature = quote { fn hash(_self: Self, _state: &mut H) where H: std::hash::Hasher }; + let for_each_field = |name| quote { _self.$name.hash(_state); }; + crate::meta::make_trait_impl( + s, + name, + signature, + for_each_field, + quote {}, + |fields| fields, + ) +} +``` +> Source code: noir_stdlib/src/hash/mod.nr#L140-L154 + + +Example deriving `Ord`: + +```rust title="derive_ord" showLineNumbers +comptime fn derive_ord(s: StructDefinition) -> Quoted { + let signature = quote { fn cmp(_self: Self, _other: Self) -> std::cmp::Ordering }; + let for_each_field = |name| quote { + if result == std::cmp::Ordering::equal() { + result = _self.$name.cmp(_other.$name); + } + }; + let body = |fields| quote { + let mut result = std::cmp::Ordering::equal(); + $fields + result + }; + crate::meta::make_trait_impl(s, quote { Ord }, signature, for_each_field, quote {}, body) +} +``` +> Source code: noir_stdlib/src/cmp.nr#L216-L231 + diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/module.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/module.md new file mode 100644 index 00000000000..f47231972b7 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/module.md @@ -0,0 +1,82 @@ +--- +title: Module +--- + +`std::meta::module` contains methods on the built-in `Module` type which represents a module in the source program. +Note that this type represents a module generally, it isn't limited to only `mod my_submodule { ... }` +declarations in the source program. + +## Methods + +### add_item + +```rust title="add_item" showLineNumbers +pub comptime fn add_item(self, item: Quoted) {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L3-L5 + + +Adds a top-level item (a function, a struct, a global, etc.) to the module. +Adding multiple items in one go is also valid if the `Quoted` value has multiple items in it. +Note that the items are type-checked as if they are inside the module they are being added to. + +### functions + +```rust title="functions" showLineNumbers +pub comptime fn functions(self) -> [FunctionDefinition] {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L18-L20 + + +Returns each function defined in the module. + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +pub comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L8-L10 + + +Returns true if this module has a custom attribute with the given name. + +### is_contract + +```rust title="is_contract" showLineNumbers +pub comptime fn is_contract(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L13-L15 + + +`true` if this module is a contract module (was declared via `contract foo { ... }`). + +### name + +```rust title="name" showLineNumbers +pub comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L28-L30 + + +Returns the name of the module. + +### structs + +```rust title="structs" showLineNumbers +pub comptime fn structs(self) -> [StructDefinition] {} +``` +> Source code: noir_stdlib/src/meta/module.nr#L23-L25 + + +Returns each struct defined in the module. + +## Trait Implementations + +```rust +impl Eq for Module +impl Hash for Module +``` + +Note that each module is assigned a unique ID internally and this is what is used for +equality and hashing. So even modules with identical names and contents may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/op.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/op.md new file mode 100644 index 00000000000..b53208d6507 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/op.md @@ -0,0 +1,244 @@ +--- +title: UnaryOp and BinaryOp +--- + +`std::meta::op` contains the `UnaryOp` and `BinaryOp` types as well as methods on them. +These types are used to represent a unary or binary operator respectively in Noir source code. + +## Types + +### UnaryOp + +Represents a unary operator. One of `-`, `!`, `&mut`, or `*`. + +### Methods + +#### is_minus + +```rust title="is_minus" showLineNumbers +pub fn is_minus(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L24-L26 + + +Returns `true` if this operator is `-`. + +#### is_not + +```rust title="is_not" showLineNumbers +pub fn is_not(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L30-L32 + + +`true` if this operator is `!` + +#### is_mutable_reference + +```rust title="is_mutable_reference" showLineNumbers +pub fn is_mutable_reference(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L36-L38 + + +`true` if this operator is `&mut` + +#### is_dereference + +```rust title="is_dereference" showLineNumbers +pub fn is_dereference(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L42-L44 + + +`true` if this operator is `*` + +#### quoted + +```rust title="unary_quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/op.nr#L48-L50 + + +Returns this operator as a `Quoted` value. + +### Trait Implementations + +```rust +impl Eq for UnaryOp +impl Hash for UnaryOp +``` + +### BinaryOp + +Represents a binary operator. One of `+`, `-`, `*`, `/`, `%`, `==`, `!=`, `<`, `<=`, `>`, `>=`, `&`, `|`, `^`, `>>`, or `<<`. + +### Methods + +#### is_add + +```rust title="is_add" showLineNumbers +pub fn is_add(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L86-L88 + + +`true` if this operator is `+` + +#### is_subtract + +```rust title="is_subtract" showLineNumbers +pub fn is_subtract(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L92-L94 + + +`true` if this operator is `-` + +#### is_multiply + +```rust title="is_multiply" showLineNumbers +pub fn is_multiply(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L98-L100 + + +`true` if this operator is `*` + +#### is_divide + +```rust title="is_divide" showLineNumbers +pub fn is_divide(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L104-L106 + + +`true` if this operator is `/` + +#### is_modulo + +```rust title="is_modulo" showLineNumbers +pub fn is_modulo(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L176-L178 + + +`true` if this operator is `%` + +#### is_equal + +```rust title="is_equal" showLineNumbers +pub fn is_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L110-L112 + + +`true` if this operator is `==` + +#### is_not_equal + +```rust title="is_not_equal" showLineNumbers +pub fn is_not_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L116-L118 + + +`true` if this operator is `!=` + +#### is_less_than + +```rust title="is_less_than" showLineNumbers +pub fn is_less_than(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L122-L124 + + +`true` if this operator is `<` + +#### is_less_than_or_equal + +```rust title="is_less_than_or_equal" showLineNumbers +pub fn is_less_than_or_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L128-L130 + + +`true` if this operator is `<=` + +#### is_greater_than + +```rust title="is_greater_than" showLineNumbers +pub fn is_greater_than(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L134-L136 + + +`true` if this operator is `>` + +#### is_greater_than_or_equal + +```rust title="is_greater_than_or_equal" showLineNumbers +pub fn is_greater_than_or_equal(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L140-L142 + + +`true` if this operator is `>=` + +#### is_and + +```rust title="is_and" showLineNumbers +pub fn is_and(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L146-L148 + + +`true` if this operator is `&` + +#### is_or + +```rust title="is_or" showLineNumbers +pub fn is_or(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L152-L154 + + +`true` if this operator is `|` + +#### is_shift_right + +```rust title="is_shift_right" showLineNumbers +pub fn is_shift_right(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L164-L166 + + +`true` if this operator is `>>` + +#### is_shift_left + +```rust title="is_shift_left" showLineNumbers +pub fn is_shift_left(self) -> bool { +``` +> Source code: noir_stdlib/src/meta/op.nr#L170-L172 + + +`true` if this operator is `<<` + +#### quoted + +```rust title="binary_quoted" showLineNumbers +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/op.nr#L182-L184 + + +Returns this operator as a `Quoted` value. + +### Trait Implementations + +```rust +impl Eq for BinaryOp +impl Hash for BinaryOp +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/quoted.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/quoted.md new file mode 100644 index 00000000000..d7acf23bc07 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/quoted.md @@ -0,0 +1,141 @@ +--- +title: Quoted +--- + +`std::meta::quoted` contains methods on the built-in `Quoted` type which represents +quoted token streams and is the result of the `quote { ... }` expression. + +## Methods + +### as_expr + +```rust title="as_expr" showLineNumbers +pub comptime fn as_expr(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L6-L8 + + +Parses the quoted token stream as an expression. Returns `Option::none()` if +the expression failed to parse. + +Example: + +```rust title="as_expr_example" showLineNumbers +#[test] + fn test_expr_as_function_call() { + comptime + { + let expr = quote { foo(42) }.as_expr().unwrap(); + let (_function, args) = expr.as_function_call().unwrap(); + assert_eq(args.len(), 1); + assert_eq(args[0].as_integer().unwrap(), (42, false)); + } + } +``` +> Source code: test_programs/noir_test_success/comptime_expr/src/main.nr#L360-L371 + + +### as_module + +```rust title="as_module" showLineNumbers +pub comptime fn as_module(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L11-L13 + + +Interprets this token stream as a module path leading to the name of a module. +Returns `Option::none()` if the module isn't found or this token stream cannot be parsed as a path. + +Example: + +```rust title="as_module_example" showLineNumbers +mod baz { + pub mod qux {} +} + +#[test] +fn as_module_test() { + comptime { + let my_mod = quote { baz::qux }.as_module().unwrap(); + assert_eq(my_mod.name(), quote { qux }); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_module/src/main.nr#L115-L127 + + +### as_trait_constraint + +```rust title="as_trait_constraint" showLineNumbers +pub comptime fn as_trait_constraint(self) -> TraitConstraint {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L16-L18 + + +Interprets this token stream as a trait constraint (without an object type). +Note that this function panics instead of returning `Option::none()` if the token +stream does not parse and resolve to a valid trait constraint. + +Example: + +```rust title="implements_example" showLineNumbers +pub fn function_with_where(_x: T) +where + T: SomeTrait, +{ + comptime { + let t = quote { T }.as_type(); + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + assert(t.implements(some_trait_i32)); + + assert(t.get_trait_impl(some_trait_i32).is_none()); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L160-L173 + + +### as_type + +```rust title="as_type" showLineNumbers +pub comptime fn as_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L21-L23 + + +Interprets this token stream as a resolved type. Panics if the token +stream doesn't parse to a type or if the type isn't a valid type in scope. + +```rust title="implements_example" showLineNumbers +pub fn function_with_where(_x: T) +where + T: SomeTrait, +{ + comptime { + let t = quote { T }.as_type(); + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + assert(t.implements(some_trait_i32)); + + assert(t.get_trait_impl(some_trait_i32).is_none()); + } +} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L160-L173 + + +### tokens + +```rust title="tokens" showLineNumbers +pub comptime fn tokens(self) -> [Quoted] {} +``` +> Source code: noir_stdlib/src/meta/quoted.nr#L26-L28 + + +Returns a slice of the individual tokens that form this token stream. + +## Trait Implementations + +```rust +impl Eq for Quoted +impl Hash for Quoted +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/struct_def.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/struct_def.md new file mode 100644 index 00000000000..fd609942f4e --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/struct_def.md @@ -0,0 +1,177 @@ +--- +title: StructDefinition +--- + +`std::meta::struct_def` contains methods on the built-in `StructDefinition` type. +This type corresponds to `struct Name { field1: Type1, ... }` items in the source program. + +## Methods + +### add_attribute + +```rust title="add_attribute" showLineNumbers +pub comptime fn add_attribute(self, attribute: str) {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L3-L5 + + +Adds an attribute to the struct. + +### add_generic + +```rust title="add_generic" showLineNumbers +pub comptime fn add_generic(self, generic_name: str) -> Type {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L8-L10 + + +Adds an generic to the struct. Returns the new generic type. +Errors if the given generic name isn't a single identifier or if +the struct already has a generic with the same name. + +This method should be used carefully, if there is existing code referring +to the struct type it may be checked before this function is called and +see the struct with the original number of generics. This method should +thus be preferred to use on code generated from other macros and structs +that are not used in function signatures. + +Example: + +```rust title="add-generic-example" showLineNumbers +comptime fn add_generic(s: StructDefinition) { + assert_eq(s.generics().len(), 0); + let new_generic = s.add_generic("T"); + + let generics = s.generics(); + assert_eq(generics.len(), 1); + assert_eq(generics[0], new_generic); + } +``` +> Source code: test_programs/compile_success_empty/comptime_struct_definition/src/main.nr#L35-L44 + + +### as_type + +```rust title="as_type" showLineNumbers +pub comptime fn as_type(self) -> Type {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L15-L17 + + +Returns this struct as a type in the source program. If this struct has +any generics, the generics are also included as-is. + +### generics + +```rust title="generics" showLineNumbers +pub comptime fn generics(self) -> [Type] {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L26-L28 + + +Returns each generic on this struct. + +Example: + +``` +#[example] +struct Foo { + bar: [T; 2], + baz: Baz, +} + +comptime fn example(foo: StructDefinition) { + assert_eq(foo.generics().len(), 2); + + // Fails because `T` isn't in scope + // let t = quote { T }.as_type(); + // assert_eq(foo.generics()[0], t); +} +``` + +### fields + +```rust title="fields" showLineNumbers +pub comptime fn fields(self) -> [(Quoted, Type)] {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L33-L35 + + +Returns each field of this struct as a pair of (field name, field type). + +### has_named_attribute + +```rust title="has_named_attribute" showLineNumbers +pub comptime fn has_named_attribute(self, name: str) -> bool {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L20-L22 + + +Returns true if this struct has a custom attribute with the given name. + +### module + +```rust title="module" showLineNumbers +pub comptime fn module(self) -> Module {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L38-L40 + + +Returns the module where the struct is defined. + +### name + +```rust title="name" showLineNumbers +pub comptime fn name(self) -> Quoted {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L43-L45 + + +Returns the name of this struct + +Note that the returned quoted value will be just the struct name, it will +not be the full path to the struct, nor will it include any generics. + +### set_fields + +```rust title="set_fields" showLineNumbers +pub comptime fn set_fields(self, new_fields: [(Quoted, Type)]) {} +``` +> Source code: noir_stdlib/src/meta/struct_def.nr#L52-L54 + + +Sets the fields of this struct to the given fields list where each element +is a pair of the field's name and the field's type. Expects each field name +to be a single identifier. Note that this will override any previous fields +on this struct. If those should be preserved, use `.fields()` to retrieve the +current fields on the struct type and append the new fields from there. + +Example: + +```rust +// Change this struct to: +// struct Foo { +// a: u32, +// b: i8, +// } +#[mangle_fields] +struct Foo { x: Field } + +comptime fn mangle_fields(s: StructDefinition) { + s.set_fields(&[ + (quote { a }, quote { u32 }.as_type()), + (quote { b }, quote { i8 }.as_type()), + ]); +} +``` + +## Trait Implementations + +```rust +impl Eq for StructDefinition +impl Hash for StructDefinition +``` + +Note that each struct is assigned a unique ID internally and this is what is used for +equality and hashing. So even structs with identical generics and fields may not +be equal in this sense if they were originally different items in the source program. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/trait_constraint.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/trait_constraint.md new file mode 100644 index 00000000000..3106f732b5a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/trait_constraint.md @@ -0,0 +1,17 @@ +--- +title: TraitConstraint +--- + +`std::meta::trait_constraint` contains methods on the built-in `TraitConstraint` type which represents +a trait constraint that can be used to search for a trait implementation. This is similar +syntactically to just the trait itself, but can also contain generic arguments. E.g. `Eq`, `Default`, +`BuildHasher`. + +This type currently has no public methods but it can be used alongside `Type` in `implements` or `get_trait_impl`. + +## Trait Implementations + +```rust +impl Eq for TraitConstraint +impl Hash for TraitConstraint +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/trait_def.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/trait_def.md new file mode 100644 index 00000000000..e661d3af7f1 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/trait_def.md @@ -0,0 +1,26 @@ +--- +title: TraitDefinition +--- + +`std::meta::trait_def` contains methods on the built-in `TraitDefinition` type. This type +represents trait definitions such as `trait Foo { .. }` at the top-level of a program. + +## Methods + +### as_trait_constraint + +```rust title="as_trait_constraint" showLineNumbers +pub comptime fn as_trait_constraint(_self: Self) -> TraitConstraint {} +``` +> Source code: noir_stdlib/src/meta/trait_def.nr#L6-L8 + + +Converts this trait into a trait constraint. If there are any generics on this +trait, they will be kept as-is without instantiating or replacing them. + +## Trait Implementations + +```rust +impl Eq for TraitDefinition +impl Hash for TraitDefinition +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/trait_impl.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/trait_impl.md new file mode 100644 index 00000000000..a527617c1e6 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/trait_impl.md @@ -0,0 +1,60 @@ +--- +title: TraitImpl +--- + +`std::meta::trait_impl` contains methods on the built-in `TraitImpl` type which represents a trait +implementation such as `impl Foo for Bar { ... }`. + +## Methods + +### trait_generic_args + +```rust title="trait_generic_args" showLineNumbers +pub comptime fn trait_generic_args(self) -> [Type] {} +``` +> Source code: noir_stdlib/src/meta/trait_impl.nr#L3-L5 + + +Returns any generic arguments on the trait of this trait implementation, if any. + +```rs +impl Foo for Bar { ... } + +comptime { + let bar_type = quote { Bar }.as_type(); + let foo = quote { Foo }.as_trait_constraint(); + + let my_impl: TraitImpl = bar_type.get_trait_impl(foo).unwrap(); + + let generics = my_impl.trait_generic_args(); + assert_eq(generics.len(), 2); + + assert_eq(generics[0], quote { i32 }.as_type()); + assert_eq(generics[1], quote { Field }.as_type()); +} +``` + +### methods + +```rust title="methods" showLineNumbers +pub comptime fn methods(self) -> [FunctionDefinition] {} +``` +> Source code: noir_stdlib/src/meta/trait_impl.nr#L8-L10 + + +Returns each method in this trait impl. + +Example: + +```rs +comptime { + let i32_type = quote { i32 }.as_type(); + let eq = quote { Eq }.as_trait_constraint(); + + let impl_eq_for_i32: TraitImpl = i32_type.get_trait_impl(eq).unwrap(); + let methods = impl_eq_for_i32.methods(); + + assert_eq(methods.len(), 1); + assert_eq(methods[0].name(), quote { eq }); +} +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/typ.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/typ.md new file mode 100644 index 00000000000..3a85a739a4c --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/typ.md @@ -0,0 +1,264 @@ +--- +title: Type +--- + +`std::meta::typ` contains methods on the built-in `Type` type used for representing +a type in the source program. + +## Functions + +```rust title="fresh_type_variable" showLineNumbers +pub comptime fn fresh_type_variable() -> Type {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L57-L59 + + +Creates and returns an unbound type variable. This is a special kind of type internal +to type checking which will type check with any other type. When it is type checked +against another type it will also be set to that type. For example, if `a` is a type +variable and we have the type equality `(a, i32) = (u8, i32)`, the compiler will set +`a` equal to `u8`. + +Unbound type variables will often be rendered as `_` while printing them. Bound type +variables will appear as the type they are bound to. + +This can be used in conjunction with functions which internally perform type checks +such as `Type::implements` or `Type::get_trait_impl` to potentially grab some of the types used. + +Note that calling `Type::implements` or `Type::get_trait_impl` on a type variable will always +fail. + +Example: + +```rust title="serialize-setup" showLineNumbers +trait Serialize {} + +impl Serialize<1> for Field {} + +impl Serialize for [T; N] +where + T: Serialize, +{} + +impl Serialize for (T, U) +where + T: Serialize, + U: Serialize, +{} +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L14-L29 + +```rust title="fresh-type-variable-example" showLineNumbers +let typevar1 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar1> }.as_trait_constraint(); + let field_type = quote { Field }.as_type(); + + // Search for a trait impl (binding typevar1 to 1 when the impl is found): + assert(field_type.implements(constraint)); + + // typevar1 should be bound to the "1" generic now: + assert_eq(typevar1.as_constant().unwrap(), 1); + + // If we want to do the same with a different type, we need to + // create a new type variable now that `typevar1` is bound + let typevar2 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar2> }.as_trait_constraint(); + let array_type = quote { [(Field, Field); 5] }.as_type(); + assert(array_type.implements(constraint)); + + // Now typevar2 should be bound to the serialized pair size 2 times the array length 5 + assert_eq(typevar2.as_constant().unwrap(), 10); +``` +> Source code: test_programs/compile_success_empty/comptime_type/src/main.nr#L129-L149 + + +## Methods + +### as_array + +```rust title="as_array" showLineNumbers +pub comptime fn as_array(self) -> Option<(Type, Type)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L76-L78 + + +If this type is an array, return a pair of (element type, size type). + +Example: + +```rust +comptime { + let array_type = quote { [Field; 3] }.as_type(); + let (field_type, three_type) = array_type.as_array().unwrap(); + + assert(field_type.is_field()); + assert_eq(three_type.as_constant().unwrap(), 3); +} +``` + +### as_constant + +```rust title="as_constant" showLineNumbers +pub comptime fn as_constant(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L83-L85 + + +If this type is a constant integer (such as the `3` in the array type `[Field; 3]`), +return the numeric constant. + +### as_integer + +```rust title="as_integer" showLineNumbers +pub comptime fn as_integer(self) -> Option<(bool, u8)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L90-L92 + + +If this is an integer type, return a boolean which is `true` +if the type is signed, as well as the number of bits of this integer type. + +### as_mutable_reference + +```rust title="as_mutable_reference" showLineNumbers +comptime fn as_mutable_reference(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L96-L98 + + +If this is a mutable reference type `&mut T`, returns the mutable type `T`. + +### as_slice + +```rust title="as_slice" showLineNumbers +pub comptime fn as_slice(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L102-L104 + + +If this is a slice type, return the element type of the slice. + +### as_str + +```rust title="as_str" showLineNumbers +pub comptime fn as_str(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L108-L110 + + +If this is a `str` type, returns the length `N` as a type. + +### as_struct + +```rust title="as_struct" showLineNumbers +pub comptime fn as_struct(self) -> Option<(StructDefinition, [Type])> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L114-L116 + + +If this is a struct type, returns the struct in addition to +any generic arguments on this type. + +### as_tuple + +```rust title="as_tuple" showLineNumbers +pub comptime fn as_tuple(self) -> Option<[Type]> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L120-L122 + + +If this is a tuple type, returns each element type of the tuple. + +### get_trait_impl + +```rust title="get_trait_impl" showLineNumbers +pub comptime fn get_trait_impl(self, constraint: TraitConstraint) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L143-L145 + + +Retrieves the trait implementation that implements the given +trait constraint for this type. If the trait constraint is not +found, `None` is returned. Note that since the concrete trait implementation +for a trait constraint specified in a `where` clause is unknown, +this function will return `None` in these cases. If you only want to know +whether a type implements a trait, use `implements` instead. + +Example: + +```rust +comptime { + let field_type = quote { Field }.as_type(); + let default = quote { Default }.as_trait_constraint(); + + let the_impl: TraitImpl = field_type.get_trait_impl(default).unwrap(); + assert(the_impl.methods().len(), 1); +} +``` + +### implements + +```rust title="implements" showLineNumbers +pub comptime fn implements(self, constraint: TraitConstraint) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L166-L168 + + +`true` if this type implements the given trait. Note that unlike +`get_trait_impl` this will also return true for any `where` constraints +in scope. + +Example: + +```rust +fn foo() where T: Default { + comptime { + let field_type = quote { Field }.as_type(); + let default = quote { Default }.as_trait_constraint(); + assert(field_type.implements(default)); + + let t = quote { T }.as_type(); + assert(t.implements(default)); + } +} +``` + +### is_bool + +```rust title="is_bool" showLineNumbers +pub comptime fn is_bool(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L172-L174 + + +`true` if this type is `bool`. + +### is_field + +```rust title="is_field" showLineNumbers +pub comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L178-L180 + + +`true` if this type is `Field`. + +### is_unit + +```rust title="is_unit" showLineNumbers +comptime fn is_unit(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L184-L186 + + +`true` if this type is the unit `()` type. + +## Trait Implementations + +```rust +impl Eq for Type +impl Hash for Type +``` +Note that this is syntactic equality, this is not the same as whether two types will type check +to be the same type. Unless type inference or generics are being used however, users should not +typically have to worry about this distinction unless `std::meta::typ::fresh_type_variable` is used. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/typed_expr.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/typed_expr.md new file mode 100644 index 00000000000..0db7dbfef61 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/typed_expr.md @@ -0,0 +1,27 @@ +--- +title: TypedExpr +--- + +`std::meta::typed_expr` contains methods on the built-in `TypedExpr` type for resolved and type-checked expressions. + +## Methods + +### get_type + +```rust title="as_function_definition" showLineNumbers +pub comptime fn as_function_definition(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typed_expr.nr#L7-L9 + + +If this expression refers to a function definitions, returns it. Otherwise returns `Option::none()`. + +### get_type + +```rust title="get_type" showLineNumbers +pub comptime fn get_type(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typed_expr.nr#L13-L15 + + +Returns the type of the expression, or `Option::none()` if there were errors when the expression was previously resolved. \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/unresolved_type.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/unresolved_type.md new file mode 100644 index 00000000000..2826ec5ec0f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/meta/unresolved_type.md @@ -0,0 +1,57 @@ +--- +title: UnresolvedType +--- + +`std::meta::unresolved_type` contains methods on the built-in `UnresolvedType` type for the syntax of types. + +## Methods + +### as_mutable_reference + +```rust title="as_mutable_reference" showLineNumbers +comptime fn as_mutable_reference(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L8-L10 + + +If this is a mutable reference type `&mut T`, returns the mutable type `T`. + +### as_slice + +```rust title="as_slice" showLineNumbers +comptime fn as_slice(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L14-L16 + + +If this is a slice `&[T]`, returns the element type `T`. + +### is_bool + +```rust title="is_bool" showLineNumbers +comptime fn is_bool(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L20-L22 + + +Returns `true` if this type is `bool`. + +### is_field + +```rust title="is_field" showLineNumbers +pub comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L26-L28 + + +Returns true if this type refers to the Field type. + +### is_unit + +```rust title="is_unit" showLineNumbers +comptime fn is_unit(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L32-L34 + + +Returns true if this type is the unit `()` type. diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/options.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/noir/standard_library/recursion.mdx b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/recursion.mdx new file mode 100644 index 00000000000..fcb36278060 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/recursion.mdx @@ -0,0 +1,67 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, verify_proof] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox'; + +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) + +## Verifying Recursive Proofs + +```rust +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} +``` + + + +## Example usage + +```rust + +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, + proof, + public_inputs, + key_hash + ); + + std::verify_proof( + verification_key, + proof_b, + public_inputs, + 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-v1.0.0-beta.1/noir/standard_library/traits.md b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/traits.md new file mode 100644 index 00000000000..ee20f9cd949 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/noir/standard_library/traits.md @@ -0,0 +1,628 @@ +--- +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 +pub trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L4-L8 + + +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 +pub 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#L28-L119 + + +#### 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 +pub 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-L26 + + +`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 +pub trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L4-L8 + + +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 +pub trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L210-L214 + + +`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 +pub trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +pub trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L60-L64 + +```rust title="mul-trait" showLineNumbers +pub trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L119-L123 + +```rust title="div-trait" showLineNumbers +pub trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L178-L182 + + +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 +pub trait Rem { + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L237-L241 + + +`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 +pub trait Neg { + fn neg(self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L290-L294 + + +`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#L296-L323 + + +### `std::ops::Not` + +```rust title="not-trait" showLineNumbers +pub 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-L60 + + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +pub trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L62-L66 + +```rust title="bitand-trait" showLineNumbers +pub trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L121-L125 + +```rust title="bitxor-trait" showLineNumbers +pub trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L180-L184 + + +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 +pub trait Shl { + fn shl(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L239-L243 + +```rust title="shr-trait" showLineNumbers +pub trait Shr { + fn shr(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L292-L296 + + +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 } } +``` + +--- + +## `std::append` + +### `std::append::Append` + +`Append` can abstract over types that can be appended to - usually container types: + +```rust title="append-trait" showLineNumbers +pub trait Append { + fn empty() -> Self; + fn append(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/append.nr#L9-L14 + + +`Append` requires two methods: + +- `empty`: Constructs an empty value of `Self`. +- `append`: Append two values together, returning the result. + +Additionally, it is expected that for any implementation: + +- `T::empty().append(x) == x` +- `x.append(T::empty()) == x` + +Implementations: +```rust +impl Append for [T] +impl Append for Quoted +``` diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/.nojekyll b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/classes/Noir.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..ead255bc504 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,52 @@ +# Noir + +## Constructors + +### new Noir(circuit) + +```ts +new Noir(circuit): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### 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) +``` + +*** + +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-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/and.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..5e3cd53e9d3 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/xor.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/index.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..4de7a696991 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/index.md @@ -0,0 +1,47 @@ +# 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. | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +## References + +### CompiledCircuit + +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-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md new file mode 100644 index 00000000000..e8c2f4aef3d --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..4796b5abaa8 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_wasm/.nojekyll b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_wasm/functions/compile.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_wasm/functions/compile_contract.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_wasm/functions/createFileManager.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_wasm/index.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/docs/versioned_docs/version-v1.0.0-beta.1/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.1/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/reference/debugger/_category_.json b/docs/versioned_docs/version-v1.0.0-beta.1/reference/debugger/_category_.json new file mode 100644 index 00000000000..27869205ad3 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/reference/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugger", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/reference/debugger/debugger_known_limitations.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/debugger/debugger_known_limitations.md new file mode 100644 index 00000000000..936d416ac4b --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/debugger/debugger_repl.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/debugger/debugger_repl.md new file mode 100644 index 00000000000..46e2011304e --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/debugger/debugger_vscode.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/debugger/debugger_vscode.md new file mode 100644 index 00000000000..c027332b3b0 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/reference/nargo_commands.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/nargo_commands.md new file mode 100644 index 00000000000..9ca8252f121 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/reference/nargo_commands.md @@ -0,0 +1,520 @@ +--- +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 check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo debug`↴](#nargo-debug) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) +* [`nargo generate-completion-script`↴](#nargo-generate-completion-script) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `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 +* `debug` — Executes a circuit in debug mode +* `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 +* `generate-completion-script` — Generates a shell completion script for your favorite shell + +###### **Options:** + + + + +## `nargo check` + +Checks the constraint system for errors + +**Usage:** `nargo check [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to run the command on. By default run on the first one found moving up along the ancestors of the current directory +* `--workspace` — Run on all packages in the workspace + + Possible values: `true`, `false` + +* `--overwrite` — Force overwrite of existing files + + Possible values: `true`, `false` + +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--skip-brillig-constraints-check` — Flag to turn off the compiler check for missing Brillig call constrains. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + Possible values: `true`, `false` + +* `--package ` — The name of the package to run the command on. By default run on the first one found moving up along the ancestors of the current directory +* `--workspace` — Run on all packages in the workspace + + Possible values: `true`, `false` + + + + +## `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 run the command on. By default run on the first one found moving up along the ancestors of the current directory +* `--workspace` — Run on all packages in the workspace + + Possible values: `true`, `false` + +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--skip-brillig-constraints-check` — Flag to turn off the compiler check for missing Brillig call constrains. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--bin` — Use a binary template [default] + + Possible values: `true`, `false` + +* `--contract` — Use a contract template + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--bin` — Use a binary template [default] + + Possible values: `true`, `false` + +* `--contract` — Use a contract template + + Possible values: `true`, `false` + + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +Defaults to the name of the package being executed. + +###### **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 run the command on. By default run on the first one found moving up along the ancestors of the current directory +* `--workspace` — Run on all packages in the workspace + + Possible values: `true`, `false` + +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--skip-brillig-constraints-check` — Flag to turn off the compiler check for missing Brillig call constrains. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo debug` + +Executes a circuit in debug mode + +**Usage:** `nargo debug [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 +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--skip-brillig-constraints-check` — Flag to turn off the compiler check for missing Brillig call constrains. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--acir-mode` — Force ACIR output (disabling instrumentation) + + Possible values: `true`, `false` + +* `--skip-instrumentation ` — Disable vars debug instrumentation (enabled by default) + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--exact` — Only run tests that match exactly + + Possible values: `true`, `false` + +* `--package ` — The name of the package to run the command on. By default run on the first one found moving up along the ancestors of the current directory +* `--workspace` — Run on all packages in the workspace + + Possible values: `true`, `false` + +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--skip-brillig-constraints-check` — Flag to turn off the compiler check for missing Brillig call constrains. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--oracle-resolver ` — JSON RPC url to solve oracle calls +* `--test-threads ` — Number of threads used for running tests in parallel + + Default value: `4` +* `--format ` — Configure formatting of output + + Possible values: + - `pretty`: + Print verbose output + - `terse`: + Display one character per test + - `json`: + Output a JSON Lines document + +* `-q`, `--quiet` — Display one character per test instead of one line + + Possible values: `true`, `false` + + + + +## `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 run the command on. By default run on the first one found moving up along the ancestors of the current directory +* `--workspace` — Run on all packages in the workspace + + Possible values: `true`, `false` + +* `--profile-execution` + + Possible values: `true`, `false` + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--expression-width ` — Specify the backend expression width that should be targeted +* `--bounded-codegen` — Generate ACIR with the target backend expression width. The default is to generate ACIR without a bound and split expressions after code generation. Activating this flag can sometimes provide optimizations for certain programs + + Default value: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--debug-comptime-in-file ` — Enable printing results of comptime evaluation: provide a path suffix for the module to debug, e.g. "package_name/src/main.nr" +* `--skip-underconstrained-check` — Flag to turn off the compiler check for under constrained values. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + +* `--skip-brillig-constraints-check` — Flag to turn off the compiler check for missing Brillig call constrains. Warning: This can improve compilation speed but can also lead to correctness errors. This check should always be run on production code + + Possible values: `true`, `false` + + + + +## `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` + + + +## `nargo generate-completion-script` + +Generates a shell completion script for your favorite shell + +**Usage:** `nargo generate-completion-script ` + +###### **Arguments:** + +* `` — The shell to generate completions for. One of: bash, elvish, fish, powershell, zsh + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/reference/noir_codegen.md b/docs/versioned_docs/version-v1.0.0-beta.1/reference/noir_codegen.md new file mode 100644 index 00000000000..e4c362f9610 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/reference/noir_codegen.md @@ -0,0 +1,116 @@ +--- +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](../getting_started/noir_installation.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"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"}},"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-v1.0.0-beta.1/tooling/debugger.md b/docs/versioned_docs/version-v1.0.0-beta.1/tooling/debugger.md new file mode 100644 index 00000000000..200b5fc423a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/tooling/debugger.md @@ -0,0 +1,26 @@ +--- +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/noir_installation.md) and vscode-noir: + +- Noir & Nargo ≥0.28.0 +- Noir's VS Code extension ≥0.0.11 + +:::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-v1.0.0-beta.1/tooling/language_server.md b/docs/versioned_docs/version-v1.0.0-beta.1/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/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-v1.0.0-beta.1/tooling/testing.md b/docs/versioned_docs/version-v1.0.0-beta.1/tooling/testing.md new file mode 100644 index 00000000000..866677da567 --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/tooling/testing.md @@ -0,0 +1,79 @@ +--- +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); +} +``` + +The string given to `should_fail_with` doesn't need to exactly match the failure reason, it just needs to be a substring of it: + +```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 = "airspeed velocity")] +fn test_bridgekeeper() { + main(32); +} +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-v1.0.0-beta.1/tutorials/noirjs_app.md b/docs/versioned_docs/version-v1.0.0-beta.1/tutorials/noirjs_app.md new file mode 100644 index 00000000000..8967ee005ce --- /dev/null +++ b/docs/versioned_docs/version-v1.0.0-beta.1/tutorials/noirjs_app.md @@ -0,0 +1,306 @@ +--- +title: Building a web app with Noir and Barretenberg +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 Typescript package meant to work both in a browser and a server environment. + +In this tutorial, we will combine NoirJS with Aztec's Barretenberg backend to build a simple web app. 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). + +## Dependencies + +Before we start, we want to make sure we have Node installed. For convenience (and speed), we can just install [Bun](https://bun.sh) as our package manager, and Node will work out-of-the-box: + +```bash +curl -fsSL https://bun.sh/install | bash +``` + +Let's go barebones. Doing the bare minimum is not only simple, but also allows you to easily adapt it to almost any frontend framework. + +Barebones means we can immediately start with the dependencies even on an empty folder 😈: + +```bash +bun i @noir-lang/noir_wasm@1.0.0-beta.0 @noir-lang/noir_js@1.0.0-beta.0 @aztec/bb.js@0.63.1 +``` + +Wait, what are these dependencies? + +- `noir_wasm` is the `wasm` version of the Noir compiler. Although most developers prefer to use `nargo` for compiling, there's nothing wrong with `noir_wasm`. We like `noir_wasm`. +- `noir_js` is the main Noir package. It will execute our program, and generate the witness that will be sent to the backend. +- `bb.js` is the Typescript interface for Aztec's Barretenberg proving backend. It also uses the `wasm` version in order to run on the browser. + +:::info + +In this guide, we will install versions pinned to 1.0.0-beta.0. These work with Barretenberg version 0.63.1, so we are using that one version too. Feel free to try with older or later versions, though! + +::: + +## Setting up our Noir program + +ZK is a powerful technology. An app that reveals computational correctness but doesn't reveal some of its inputs is almost unbelievable, yet Noir makes it as easy as a single line of code. + +:::tip + +It's not just you. We also enjoy syntax highlighting. [Check out the Language Server](../tooling/language_server.md) + +::: + +All you need is a `main.nr` and a `Nargo.toml` file. You can follow the [noirup](../getting_started/noir_installation.md) installation and just run `noirup -v 1.0.0-beta.0`, or just create them by hand: + +```bash +mkdir -p circuit/src +touch circuit/src/main.nr circuit/Nargo.toml +``` + +To make our program interesting, let's give it a real use-case scenario: Bob wants to prove he is older than 18, without disclosing his age. Open `main.nr` and write: + +```rust +fn main(age: u8) { + assert(age >= 18); +} +``` + +This program accepts a private input called age, and simply proves this number is higher than 18. But to run this code, we need to give the compiler a `Nargo.toml` with at least a name and a type: + +```toml +[package] +name = "circuit" +type = "bin" +``` + +This is all that we need to get started with Noir. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## Setting up our app + +Remember when apps only had one `html` and one `js` file? Well, that's enough for Noir webapps. Let's create them: + +```bash +touch index.html index.js +``` + +And add something useful to our HTML file: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It _could_ be a beautiful UI... Depending on which universe you live in. In any case, we're using some scary CSS to make two boxes that will show cool things on the screen. + +As for the JS, real madmen could just `console.log` everything, but let's say we want to see things happening (the true initial purpose of JS... right?). Here's some boilerplate for that. Just paste it in `index.js`: + +```js +const show = (id, content) => { + const container = document.getElementById(id); + container.appendChild(document.createTextNode(content)); + container.appendChild(document.createElement("br")); +}; + +document.getElementById("submit").addEventListener("click", async () => { + try { + // noir goes here + } catch { + show("logs", "Oh 💔"); + } +}); + +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── src + └── main.nr + Nargo.toml + index.js + package.json + index.html + ...etc +``` + +::: + +## Compile compile compile + +Finally we're up for something cool. But before we can execute a Noir program, we need to compile it into ACIR: an abstract representation. Here's where `noir_wasm` comes in. + +`noir_wasm` expects a filesystem so it can resolve dependencies. While we could use the `public` folder, let's just import those using the nice `?url` syntax provided by vite. At the top of the file: + +```js +import { compile, createFileManager } from "@noir-lang/noir_wasm" + +import main from "./circuit/src/main.nr?url"; +import nargoToml from "./circuit/Nargo.toml?url"; +``` + +Compiling on the browser is common enough that `createFileManager` already gives us a nice in-memory filesystem we can use. So all we need to compile is fetching these files, writing them to our filesystem, and compile. Add this function: + +```js +export async function getCircuit() { + const fm = createFileManager("/"); + const { body } = await fetch(main); + const { body: nargoTomlBody } = await fetch(nargoToml); + + fm.writeFile("./src/main.nr", body); + fm.writeFile("./Nargo.toml", nargoTomlBody); + return await compile(fm); +} +``` + +:::tip + +As you can imagine, with `node` it's all conveniently easier since you get native access to `fs`... + +::: + +## Some more JS + +We're starting with the good stuff now. We want to execute our circuit to get the witness, and then feed that witness to Barretenberg. Luckily, both packages are quite easy to work with. Let's import them at the top of the file: + +```js +import { UltraHonkBackend } from '@aztec/bb.js'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const { program } = await getCircuit(); +const noir = new Noir(program); +const backend = new UltraHonkBackend(program.bytecode); +// } +``` + +:::warning + +WASMs are not always easy to work with. In our case, `vite` likes serving them with the wrong MIME type. There are different fixes but we found the easiest one is just YOLO instantiating the WASMs manually. Paste this at the top of the file, just below the other imports, and it will work just fine: + +```js +import initNoirC from "@noir-lang/noirc_abi"; +import initACVM from "@noir-lang/acvm_js"; +import acvm from "@noir-lang/acvm_js/web/acvm_js_bg.wasm?url"; +import noirc from "@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm?url"; +await Promise.all([initACVM(fetch(acvm)), initNoirC(fetch(noirc))]); +``` + +::: + +## Executing and proving + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Inside our `try` block, let's just grab that input and get its value. Noir will gladly execute it, and give us a witness: + +```js +const age = document.getElementById("age").value; +show("logs", "Generating witness... ⏳"); +const { witness } = await noir.execute({ age }); +show("logs", "Generated witness... ✅"); + +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +show("logs", "Generating proof... ⏳"); +const proof = await backend.generateProof(witness); +show("logs", "Generated proof... ✅"); +show("results", proof.proof); +``` + +Our program is technically **done** . You're probably eager to see stuff happening! To serve this in a convenient way, we can use a bundler like `vite` by creating a `vite.config.js` file: + +```bash +touch vite.config.js +``` + +`vite` helps us with a little catch: `bb.js` in particular uses top-level awaits which aren't supported everywhere. So we can add this to the `vite.config.js` to make the bundler optimize them: + +```js +export default { optimizeDeps: { esbuildOptions: { target: "esnext" } } }; +``` + +This should be enough for vite. We don't even need to install it, just run: + +```bash +bunx vite +``` + +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. + +![Noir Webapp UI](@site/static/img/tutorials/noirjs_webapp/webapp1.png) + +Now, our circuit requires a private input `fn main(age: u8)`, and fails if it is less than 18. Let's see if it works. Submit any number above 18 (as long as it fits in 8 bits) and 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 +show('logs', 'Verifying proof... ⌛'); +const isValid = await backend.verifyProof(proof); +show("logs", `Proof is ${isValid ? "valid" : "invalid"}... ✅`); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## Next steps + +At this point, you have a working ZK app that works on the browser. Actually, it works on a mobile phone too! + +If you want to continue learning by doing, here are some challenges for you: + +- Install [nargo](https://noir-lang.org/docs/getting_started/noir_installation) and write [Noir tests](../tooling/testing) +- Change the circuit to accept a [public input](../noir/concepts/data_types/#private--public-types) as the cutoff age. It could be different depending on the purpose, for example! +- Enjoy Noir's Rust-like syntax and write a struct `Country` that implements a trait `MinAge` with a method `get_min_age`. Then, make a struct `Person` have an `u8` as its age and a country of type `Country`. You can pass a `person` in JS just like a JSON object `person: { age, country: { min_age: 18 }}` + +The world is your stage, just have fun with ZK! 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. + +Check out other starters, tools, or just cool projects in the [awesome noir repository](https://github.com/noir-lang/awesome-noir). diff --git a/docs/versioned_sidebars/version-v0.36.0-sidebars.json b/docs/versioned_sidebars/version-v0.36.0-sidebars.json new file mode 100644 index 00000000000..b9ad026f69f --- /dev/null +++ b/docs/versioned_sidebars/version-v0.36.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-v1.0.0-beta.0-sidebars.json b/docs/versioned_sidebars/version-v1.0.0-beta.0-sidebars.json new file mode 100644 index 00000000000..b9ad026f69f --- /dev/null +++ b/docs/versioned_sidebars/version-v1.0.0-beta.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-v1.0.0-beta.1-sidebars.json b/docs/versioned_sidebars/version-v1.0.0-beta.1-sidebars.json new file mode 100644 index 00000000000..b9ad026f69f --- /dev/null +++ b/docs/versioned_sidebars/version-v1.0.0-beta.1-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/.gitignore b/examples/.gitignore new file mode 100644 index 00000000000..c4fdcad6719 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,2 @@ +target +proofs \ No newline at end of file diff --git a/examples/codegen_verifier/.gitignore b/examples/codegen_verifier/.gitignore new file mode 100644 index 00000000000..ae13a24752c --- /dev/null +++ b/examples/codegen_verifier/.gitignore @@ -0,0 +1,3 @@ +out +cache +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/examples/codegen_verifier/Prover.toml b/examples/codegen_verifier/Prover.toml new file mode 100644 index 00000000000..2c1854573a4 --- /dev/null +++ b/examples/codegen_verifier/Prover.toml @@ -0,0 +1,2 @@ +x = 1 +y = 2 diff --git a/examples/codegen_verifier/codegen_verifier.sh b/examples/codegen_verifier/codegen_verifier.sh new file mode 100755 index 00000000000..9d1a6251dde --- /dev/null +++ b/examples/codegen_verifier/codegen_verifier.sh @@ -0,0 +1,43 @@ +#!/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 --pedantic-solving witness + +PROOF_PATH=./target/proof +$BACKEND prove -b ./target/hello_world.json -w ./target/witness.gz -o $PROOF_PATH + +# Sanity check that proof is valid. +$BACKEND verify -k ./target/vk -p ./target/proof + +NUM_PUBLIC_INPUTS=2 +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') + +# Split public inputs into strings where each string represents a `bytes32`. +SPLIT_HEX_PUBLIC_INPUTS=$(sed -e 's/.\{64\}/0x&,/g' <<< $HEX_PUBLIC_INPUTS) + +# 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. +cast call $VERIFIER_ADDRESS "verify(bytes, bytes32[])(bool)" "0x$HEX_PROOF" "[$SPLIT_HEX_PUBLIC_INPUTS]" + +# Stop anvil node again +kill %- 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..93531797744 --- /dev/null +++ b/examples/codegen_verifier/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: pub Field, y: pub Field) { + assert(x != y); +} 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/examples/prove_and_verify/Prover.toml b/examples/prove_and_verify/Prover.toml new file mode 100644 index 00000000000..8c12ebba6cf --- /dev/null +++ b/examples/prove_and_verify/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "2" 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..411f5258caf --- /dev/null +++ b/examples/prove_and_verify/prove_and_verify.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -eu + +BACKEND=${BACKEND:-bb} + +nargo execute --pedantic-solving 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 -k ./target/vk -p ./proofs/proof 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/examples/recursion/.gitignore b/examples/recursion/.gitignore new file mode 100644 index 00000000000..12587094b0f --- /dev/null +++ b/examples/recursion/.gitignore @@ -0,0 +1,2 @@ +recurse_leaf/Prover.toml +recurse_node/Prover.toml \ No newline at end of file diff --git a/examples/recursion/Nargo.toml b/examples/recursion/Nargo.toml new file mode 100644 index 00000000000..7c7a8b1926f --- /dev/null +++ b/examples/recursion/Nargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["recurse_leaf", "recurse_node", "sum"] diff --git a/examples/recursion/generate_recursive_proof.sh b/examples/recursion/generate_recursive_proof.sh new file mode 100755 index 00000000000..09b01d547b6 --- /dev/null +++ b/examples/recursion/generate_recursive_proof.sh @@ -0,0 +1,61 @@ +#!/bin/bash +set -eu + +BACKEND=${BACKEND:-bb} + +nargo execute sum_witness --package sum +$BACKEND prove -b ./target/sum.json -w ./target/sum_witness.gz -o ./target/sum_proof --recursive + +# Once we have generated our inner proof, we must use this to generate inputs to `recurse_leaf`` + +$BACKEND write_vk -b ./target/sum.json -o ./target/sum_key --recursive +$BACKEND vk_as_fields -k ./target/sum_key -o ./target/sum_vk_as_fields +VK_HASH=$(jq -r '.[0]' ./target/sum_vk_as_fields) +VK_AS_FIELDS=$(jq -r '.[1:]' ./target/sum_vk_as_fields) + +FULL_PROOF_AS_FIELDS="$($BACKEND proof_as_fields -p ./target/sum_proof -k ./target/sum_key -o -)" +# sum has 3 public inputs +PUBLIC_INPUTS=$(echo $FULL_PROOF_AS_FIELDS | jq -r '.[:3]') +PROOF_AS_FIELDS=$(echo $FULL_PROOF_AS_FIELDS | jq -r '.[3:]') + +RECURSE_LEAF_PROVER_TOML=./recurse_leaf/Prover.toml +echo "num = 2" > $RECURSE_LEAF_PROVER_TOML +echo "key_hash = \"$VK_HASH\"" >> $RECURSE_LEAF_PROVER_TOML +echo "verification_key = $VK_AS_FIELDS" >> $RECURSE_LEAF_PROVER_TOML +echo "proof = $PROOF_AS_FIELDS" >> $RECURSE_LEAF_PROVER_TOML +echo "public_inputs = $PUBLIC_INPUTS" >> $RECURSE_LEAF_PROVER_TOML + +# We can now execute and prove `recurse_leaf` + +nargo execute recurse_leaf_witness --package recurse_leaf +$BACKEND prove -b ./target/recurse_leaf.json -w ./target/recurse_leaf_witness.gz -o ./target/recurse_leaf_proof --recursive + +# Let's do a sanity check that the proof we've generated so far is valid. +$BACKEND write_vk -b ./target/recurse_leaf.json -o ./target/recurse_leaf_key --recursive +$BACKEND verify -p ./target/recurse_leaf_proof -k ./target/recurse_leaf_key + +# Now we generate the final `recurse_node` proof similarly to how we did for `recurse_leaf`. + +$BACKEND vk_as_fields -k ./target/recurse_leaf_key -o ./target/recurse_leaf_vk_as_fields +VK_HASH=$(jq -r '.[0]' ./target/recurse_leaf_vk_as_fields) +VK_AS_FIELDS=$(jq -r '.[1:]' ./target/recurse_leaf_vk_as_fields) + +FULL_PROOF_AS_FIELDS="$($BACKEND proof_as_fields -p ./target/recurse_leaf_proof -k ./target/recurse_leaf_key -o -)" +# recurse_leaf has 4 public inputs (excluding aggregation object) +PUBLIC_INPUTS=$(echo $FULL_PROOF_AS_FIELDS | jq -r '.[:4]') +PROOF_AS_FIELDS=$(echo $FULL_PROOF_AS_FIELDS | jq -r '.[4:]') + +RECURSE_NODE_PROVER_TOML=./recurse_node/Prover.toml +echo "key_hash = \"$VK_HASH\"" > $RECURSE_NODE_PROVER_TOML +echo "verification_key = $VK_AS_FIELDS" >> $RECURSE_NODE_PROVER_TOML +echo "proof = $PROOF_AS_FIELDS" >> $RECURSE_NODE_PROVER_TOML +echo "public_inputs = $PUBLIC_INPUTS" >> $RECURSE_NODE_PROVER_TOML + +# We can now execute and prove `recurse_node` + +nargo execute recurse_node_witness --package recurse_node +$BACKEND prove -b ./target/recurse_node.json -w ./target/recurse_node_witness.gz -o ./target/recurse_node_proof + +# We finally verify that the generated recursive proof is valid. +$BACKEND write_vk -b ./target/recurse_node.json -o ./target/recurse_node_key +$BACKEND verify -p ./target/recurse_node_proof -k ./target/recurse_node_key diff --git a/examples/recursion/recurse_leaf/Nargo.toml b/examples/recursion/recurse_leaf/Nargo.toml new file mode 100644 index 00000000000..7af9cd74940 --- /dev/null +++ b/examples/recursion/recurse_leaf/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "recurse_leaf" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/examples/recursion/recurse_leaf/src/main.nr b/examples/recursion/recurse_leaf/src/main.nr new file mode 100644 index 00000000000..0031997160d --- /dev/null +++ b/examples/recursion/recurse_leaf/src/main.nr @@ -0,0 +1,12 @@ +fn main( + verification_key: [Field; 114], + public_inputs: pub [Field; 3], + key_hash: Field, + proof: [Field; 93], + num: u64, +) -> pub u64 { + // verify sum so far was computed correctly + std::verify_proof(verification_key, proof, public_inputs, key_hash); + // Take output of previous proof and add another number to it. + public_inputs[2] as u64 + num +} diff --git a/examples/recursion/recurse_node/Nargo.toml b/examples/recursion/recurse_node/Nargo.toml new file mode 100644 index 00000000000..db4b3b77693 --- /dev/null +++ b/examples/recursion/recurse_node/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "recurse_node" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/examples/recursion/recurse_node/src/main.nr b/examples/recursion/recurse_node/src/main.nr new file mode 100644 index 00000000000..05b717fc794 --- /dev/null +++ b/examples/recursion/recurse_node/src/main.nr @@ -0,0 +1,10 @@ +fn main( + verification_key: [Field; 114], + public_inputs: pub [Field; 4], + key_hash: Field, + proof: [Field; 109] +) -> pub u64 { + // verify sum was computed correctly + std::verify_proof(verification_key, proof, public_inputs, key_hash); + public_inputs[3] as u64 +} diff --git a/examples/recursion/sum/Nargo.toml b/examples/recursion/sum/Nargo.toml new file mode 100644 index 00000000000..7a5f1498c3e --- /dev/null +++ b/examples/recursion/sum/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "sum" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/examples/recursion/sum/Prover.toml b/examples/recursion/sum/Prover.toml new file mode 100644 index 00000000000..eae66cb8593 --- /dev/null +++ b/examples/recursion/sum/Prover.toml @@ -0,0 +1,2 @@ +a = 1 +b = 2 \ No newline at end of file diff --git a/examples/recursion/sum/src/main.nr b/examples/recursion/sum/src/main.nr new file mode 100644 index 00000000000..e8cd9f2aff9 --- /dev/null +++ b/examples/recursion/sum/src/main.nr @@ -0,0 +1,3 @@ +fn main(a: pub u64, b: pub u64) -> pub u64 { + a + b +} diff --git a/examples/recursion/test.sh b/examples/recursion/test.sh new file mode 100755 index 00000000000..1e9eca35cab --- /dev/null +++ b/examples/recursion/test.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -eu + +# This file is used for Noir CI and is not required. + +BACKEND=${BACKEND:-bb} + +./generate_recursive_proof.sh \ No newline at end of file diff --git a/noir-logo.png b/noir-logo.png new file mode 100644 index 00000000000..0abffba22ef Binary files /dev/null and b/noir-logo.png differ diff --git a/noir_stdlib/Nargo.toml b/noir_stdlib/Nargo.toml new file mode 100644 index 00000000000..d2f8ebcb636 --- /dev/null +++ b/noir_stdlib/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "std" +type = "lib" +authors = [""] +[dependencies] diff --git a/noir_stdlib/src/aes128.nr b/noir_stdlib/src/aes128.nr new file mode 100644 index 00000000000..d781812eee9 --- /dev/null +++ b/noir_stdlib/src/aes128.nr @@ -0,0 +1,8 @@ +#[foreign(aes128_encrypt)] +// docs:start:aes128 +pub fn aes128_encrypt( + input: [u8; N], + iv: [u8; 16], + key: [u8; 16], +) -> [u8; N + 16 - N % 16] {} +// docs:end:aes128 diff --git a/noir_stdlib/src/append.nr b/noir_stdlib/src/append.nr new file mode 100644 index 00000000000..5f41dae8046 --- /dev/null +++ b/noir_stdlib/src/append.nr @@ -0,0 +1,35 @@ +// Appends two values together, returning the result. +// +// An alternate name for this trait is `Monoid` if that is familiar. +// If not, it can be ignored. +// +// It is expected that for any implementation: +// - `T::empty().append(x) == x` +// - `x.append(T::empty()) == x` +// docs:start:append-trait +pub trait Append { + fn empty() -> Self; + fn append(self, other: Self) -> Self; +} +// docs:end:append-trait + +impl Append for [T] { + fn empty() -> Self { + &[] + } + + fn append(self, other: Self) -> Self { + // Slices have an existing append function which this will resolve to. + self.append(other) + } +} + +impl Append for Quoted { + comptime fn empty() -> Self { + quote {} + } + + comptime fn append(self, other: Self) -> Self { + quote { $self $other } + } +} diff --git a/noir_stdlib/src/array/check_shuffle.nr b/noir_stdlib/src/array/check_shuffle.nr new file mode 100644 index 00000000000..327f0559810 --- /dev/null +++ b/noir_stdlib/src/array/check_shuffle.nr @@ -0,0 +1,124 @@ +use crate::cmp::Eq; + +unconstrained fn __get_shuffle_indices(lhs: [T; N], rhs: [T; N]) -> [Field; N] +where + T: Eq, +{ + let mut shuffle_indices: [Field; N] = [0; N]; + + let mut shuffle_mask: [bool; N] = [false; N]; + for i in 0..N { + let mut found = false; + for j in 0..N { + if ((shuffle_mask[j] == false) & (!found)) { + if (lhs[i] == rhs[j]) { + found = true; + shuffle_indices[i] = j as Field; + shuffle_mask[j] = true; + } + } + if (found) { + continue; + } + } + assert(found == true, "check_shuffle, lhs and rhs arrays do not contain equivalent values"); + } + + shuffle_indices +} + +unconstrained fn __get_index(indices: [Field; N], idx: Field) -> Field { + let mut result = 0; + for i in 0..N { + if (indices[i] == idx) { + result = i as Field; + break; + } + } + result +} + +pub(crate) fn check_shuffle(lhs: [T; N], rhs: [T; N]) +where + T: Eq, +{ + /// Safety: shuffle_indices is ensured to be a permutation of 0..N, and then + /// shuffle_indices is ensured to map lhs to rhs: assert(lhs[i] == rhs[shuffle_indices[i]]), for all i in 0..N + unsafe { + let shuffle_indices = __get_shuffle_indices(lhs, rhs); + + for i in 0..N { + let idx = __get_index(shuffle_indices, i as Field); + assert_eq(shuffle_indices[idx], i as Field); + } + for i in 0..N { + let idx = shuffle_indices[i]; + let expected = rhs[idx]; + let result = lhs[i]; + assert_eq(expected, result); + } + } +} + +mod test { + use crate::cmp::Eq; + use super::check_shuffle; + + struct CompoundStruct { + a: bool, + b: Field, + c: u64, + } + impl Eq for CompoundStruct { + fn eq(self, other: Self) -> bool { + (self.a == other.a) & (self.b == other.b) & (self.c == other.c) + } + } + + #[test] + fn test_shuffle() { + let lhs: [Field; 5] = [0, 1, 2, 3, 4]; + let rhs: [Field; 5] = [2, 0, 3, 1, 4]; + check_shuffle(lhs, rhs); + } + + #[test] + fn test_shuffle_identity() { + let lhs: [Field; 5] = [0, 1, 2, 3, 4]; + let rhs: [Field; 5] = [0, 1, 2, 3, 4]; + check_shuffle(lhs, rhs); + } + + #[test(should_fail_with = "check_shuffle, lhs and rhs arrays do not contain equivalent values")] + fn test_shuffle_fail() { + let lhs: [Field; 5] = [0, 1, 2, 3, 4]; + let rhs: [Field; 5] = [0, 1, 2, 3, 5]; + check_shuffle(lhs, rhs); + } + + #[test(should_fail_with = "check_shuffle, lhs and rhs arrays do not contain equivalent values")] + fn test_shuffle_duplicates() { + let lhs: [Field; 5] = [0, 1, 2, 3, 4]; + let rhs: [Field; 5] = [0, 1, 2, 3, 3]; + check_shuffle(lhs, rhs); + } + + #[test] + fn test_shuffle_compound_struct() { + let lhs: [CompoundStruct; 5] = [ + CompoundStruct { a: false, b: 0, c: 12345 }, + CompoundStruct { a: false, b: -100, c: 54321 }, + CompoundStruct { a: true, b: 5, c: 0xffffffffffffffff }, + CompoundStruct { a: true, b: 9814, c: 0xeeffee0011001133 }, + CompoundStruct { a: false, b: 0x155, c: 0 }, + ]; + let rhs: [CompoundStruct; 5] = [ + CompoundStruct { a: false, b: 0x155, c: 0 }, + CompoundStruct { a: false, b: 0, c: 12345 }, + CompoundStruct { a: false, b: -100, c: 54321 }, + CompoundStruct { a: true, b: 9814, c: 0xeeffee0011001133 }, + CompoundStruct { a: true, b: 5, c: 0xffffffffffffffff }, + ]; + check_shuffle(lhs, rhs); + } +} diff --git a/noir_stdlib/src/array/mod.nr b/noir_stdlib/src/array/mod.nr new file mode 100644 index 00000000000..47dc3ca7bb9 --- /dev/null +++ b/noir_stdlib/src/array/mod.nr @@ -0,0 +1,235 @@ +use crate::cmp::{Eq, Ord}; +use crate::convert::From; +use crate::runtime::is_unconstrained; + +mod check_shuffle; +mod quicksort; + +impl [T; N] { + /// Returns the length of this array. + /// + /// ```noir + /// fn len(self) -> Field + /// ``` + /// + /// example + /// + /// ```noir + /// fn main() { + /// let array = [42, 42]; + /// assert(array.len() == 2); + /// } + /// ``` + #[builtin(array_len)] + pub fn len(self) -> u32 {} + + /// Returns this array as a slice. + /// + /// ```noir + /// let array = [1, 2]; + /// let slice = array.as_slice(); + /// assert_eq(slice, &[1, 2]); + /// ``` + #[builtin(as_slice)] + pub fn as_slice(self) -> [T] {} + + /// Applies a function to each element of this array, returning a new array containing the mapped elements. + /// + /// Example: + /// + /// ```rust + /// let a = [1, 2, 3]; + /// let b = a.map(|a| a * 2); + /// assert_eq(b, [2, 4, 6]); + /// ``` + pub fn map(self, f: fn[Env](T) -> U) -> [U; N] { + let uninitialized = crate::mem::zeroed(); + let mut ret = [uninitialized; N]; + + for i in 0..self.len() { + ret[i] = f(self[i]); + } + + ret + } + + /// Applies a function to each element of the array, returning the final accumulated value. The first + /// parameter is the initial value. + /// + /// 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) + /// + /// assert_eq(a3.fold(10, f), 10 - 1 - 2 - 3); + /// ``` + pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U { + for elem in self { + accumulator = f(accumulator, elem); + } + accumulator + } + + /// Same as fold, but uses the first element as the starting element. + /// + /// Requires the input array to be non-empty. + /// + /// Example: + /// + /// ```noir + /// fn main() { + /// let arr = [1, 2, 3, 4]; + /// let reduced = arr.reduce(|a, b| a + b); + /// assert(reduced == 10); + /// } + /// ``` + pub fn reduce(self, f: fn[Env](T, T) -> T) -> T { + let mut accumulator = self[0]; + for i in 1..self.len() { + accumulator = f(accumulator, self[i]); + } + accumulator + } + + /// Returns true if all the elements in this array satisfy the given predicate. + /// + /// Example: + /// + /// ```noir + /// fn main() { + /// let arr = [2, 2, 2, 2, 2]; + /// let all = arr.all(|a| a == 2); + /// assert(all); + /// } + /// ``` + pub fn all(self, predicate: fn[Env](T) -> bool) -> bool { + let mut ret = true; + for elem in self { + ret &= predicate(elem); + } + ret + } + + /// Returns true if any of the elements in this array satisfy the given predicate. + /// + /// Example: + /// + /// ```noir + /// fn main() { + /// let arr = [2, 2, 2, 2, 5]; + /// let any = arr.any(|a| a == 5); + /// assert(any); + /// } + /// ``` + pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { + let mut ret = false; + for elem in self { + ret |= predicate(elem); + } + ret + } +} + +impl [T; N] +where + T: Ord + Eq, +{ + /// 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 `sort_via` function. + /// + /// Example: + /// + /// ```rust + /// fn main() { + /// let arr = [42, 32]; + /// let sorted = arr.sort(); + /// assert(sorted == [32, 42]); + /// } + /// ``` + pub fn sort(self) -> Self { + self.sort_via(|a: T, b: T| a <= b) + } +} + +impl [T; N] +where + T: Eq, +{ + /// Returns a new sorted array by sorting it with a custom comparison function. + /// The original array remains untouched. + /// The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument. + /// + /// Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements. + /// + /// 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 + /// } + /// ``` + pub fn sort_via(self, ordering: fn[Env](T, T) -> bool) -> Self { + /// Safety: `sorted` array is checked to be: + /// a. a permutation of `input`'s elements + /// b. satisfying the predicate `ordering` + unsafe { + let sorted = quicksort::quicksort(self, ordering); + + if !is_unconstrained() { + for i in 0..N - 1 { + assert( + ordering(sorted[i], sorted[i + 1]), + "Array has not been sorted correctly according to `ordering`.", + ); + } + check_shuffle::check_shuffle(self, sorted); + } + sorted + } + } +} + +impl [u8; N] { + /// Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation - + /// the given array is interpreted as-is as a string. + /// + /// Example: + /// + /// ```rust + /// fn main() { + /// let hi = [104, 105].as_str_unchecked(); + /// assert_eq(hi, "hi"); + /// } + /// ``` + #[builtin(array_as_str_unchecked)] + pub fn as_str_unchecked(self) -> str {} +} + +impl From> for [u8; N] { + /// Returns an array of the string bytes. + fn from(s: str) -> Self { + s.as_bytes() + } +} + +mod test { + #[test] + fn map_empty() { + assert_eq([].map(|x| x + 1), []); + } +} diff --git a/noir_stdlib/src/array/quicksort.nr b/noir_stdlib/src/array/quicksort.nr new file mode 100644 index 00000000000..5e9c575c5ce --- /dev/null +++ b/noir_stdlib/src/array/quicksort.nr @@ -0,0 +1,47 @@ +unconstrained fn partition( + arr: &mut [T; N], + low: u32, + high: u32, + sortfn: fn[Env](T, T) -> bool, +) -> u32 { + let pivot = high; + let mut i = low; + for j in low..high { + if (sortfn(arr[j], arr[pivot])) { + let temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + i += 1; + } + } + let temp = arr[i]; + arr[i] = arr[pivot]; + arr[pivot] = temp; + i +} + +unconstrained fn quicksort_recursive( + arr: &mut [T; N], + low: u32, + high: u32, + sortfn: fn[Env](T, T) -> bool, +) { + if low < high { + let pivot_index = partition(arr, low, high, sortfn); + if pivot_index > 0 { + quicksort_recursive(arr, low, pivot_index - 1, sortfn); + } + quicksort_recursive(arr, pivot_index + 1, high, sortfn); + } +} + +pub(crate) unconstrained fn quicksort( + _arr: [T; N], + sortfn: fn[Env](T, T) -> bool, +) -> [T; N] { + let mut arr: [T; N] = _arr; + if arr.len() <= 1 {} else { + quicksort_recursive(&mut arr, 0, arr.len() - 1, sortfn); + } + arr +} diff --git a/noir_stdlib/src/bigint.nr b/noir_stdlib/src/bigint.nr new file mode 100644 index 00000000000..6ce3ea7d72a --- /dev/null +++ b/noir_stdlib/src/bigint.nr @@ -0,0 +1,406 @@ +use crate::cmp::Eq; +use crate::ops::{Add, Div, Mul, Sub}; + +global bn254_fq: [u8] = &[ + 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: [u8] = &[ + 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: [u8] = &[ + 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: [u8] = &[ + 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: [u8] = &[ + 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: [u8] = &[ + 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 +pub struct BigInt { + pointer: u32, + modulus: u32, +} +// docs:end:big_int_definition + +impl BigInt { + #[foreign(bigint_add)] + fn bigint_add(self, other: BigInt) -> BigInt {} + #[foreign(bigint_sub)] + fn bigint_sub(self, other: BigInt) -> BigInt {} + #[foreign(bigint_mul)] + fn bigint_mul(self, other: BigInt) -> BigInt {} + #[foreign(bigint_div)] + fn bigint_div(self, other: BigInt) -> BigInt {} + #[foreign(bigint_from_le_bytes)] + fn from_le_bytes(bytes: [u8], modulus: [u8]) -> BigInt {} + #[foreign(bigint_to_le_bytes)] + fn to_le_bytes(self) -> [u8; 32] {} + + fn check_32_bytes(self: Self, other: BigInt) -> bool { + let bytes = self.to_le_bytes(); + let o_bytes = other.to_le_bytes(); + let mut result = true; + for i in 0..32 { + result = result & (bytes[i] == o_bytes[i]); + } + result + } +} + +pub trait BigField { + fn from_le_bytes(bytes: [u8]) -> Self; + fn from_le_bytes_32(bytes: [u8; 32]) -> Self; + fn to_le_bytes(self) -> [u8]; +} + +pub struct Secpk1Fq { + 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 } + } + + fn from_le_bytes_32(bytes: [u8; 32]) -> Secpk1Fq { + Secpk1Fq { array: bytes } + } + + fn to_le_bytes(self) -> [u8] { + 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 { 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 { 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 { 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 { array: a.bigint_div(b).to_le_bytes() } + } +} +impl Eq for Secpk1Fq { + fn eq(self: Self, other: Secpk1Fq) -> bool { + self.array == other.array + } +} + +pub struct Secpk1Fr { + 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 { array } + } + + fn from_le_bytes_32(bytes: [u8; 32]) -> Secpk1Fr { + Secpk1Fr { array: bytes } + } + + fn to_le_bytes(self) -> [u8] { + 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 { 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 { 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 { 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 { array: a.bigint_div(b).to_le_bytes() } + } +} +impl Eq for Secpk1Fr { + fn eq(self: Self, other: Secpk1Fr) -> bool { + self.array == other.array + } +} + +pub struct Bn254Fr { + 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 } + } + + fn from_le_bytes_32(bytes: [u8; 32]) -> Bn254Fr { + Bn254Fr { array: bytes } + } + + fn to_le_bytes(self) -> [u8] { + 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 { 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 { 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 { 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 { array: a.bigint_div(b).to_le_bytes() } + } +} +impl Eq for Bn254Fr { + fn eq(self: Self, other: Bn254Fr) -> bool { + self.array == other.array + } +} + +pub struct Bn254Fq { + 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 } + } + + fn from_le_bytes_32(bytes: [u8; 32]) -> Bn254Fq { + Bn254Fq { array: bytes } + } + + fn to_le_bytes(self) -> [u8] { + 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 { 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 { 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 { 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 { array: a.bigint_div(b).to_le_bytes() } + } +} +impl Eq for Bn254Fq { + fn eq(self: Self, other: Bn254Fq) -> bool { + self.array == other.array + } +} + +pub struct Secpr1Fq { + 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 { array } + } + + fn from_le_bytes_32(bytes: [u8; 32]) -> Secpr1Fq { + Secpr1Fq { array: bytes } + } + + fn to_le_bytes(self) -> [u8] { + 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 { 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 { 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 { 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 { array: a.bigint_div(b).to_le_bytes() } + } +} +impl Eq for Secpr1Fq { + fn eq(self: Self, other: Secpr1Fq) -> bool { + self.array == other.array + } +} + +pub struct Secpr1Fr { + 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 } + } + + fn from_le_bytes_32(bytes: [u8; 32]) -> Secpr1Fr { + Secpr1Fr { array: bytes } + } + + fn to_le_bytes(self) -> [u8] { + 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 { 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 { 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 { 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 { array: a.bigint_div(b).to_le_bytes() } + } +} +impl Eq for Secpr1Fr { + fn eq(self: Self, other: Secpr1Fr) -> bool { + self.array == other.array + } +} diff --git a/noir_stdlib/src/cmp.nr b/noir_stdlib/src/cmp.nr new file mode 100644 index 00000000000..7f19594c30e --- /dev/null +++ b/noir_stdlib/src/cmp.nr @@ -0,0 +1,557 @@ +use crate::meta::derive_via; + +#[derive_via(derive_eq)] +// docs:start:eq-trait +pub trait Eq { + fn eq(self, other: Self) -> bool; +} +// docs:end:eq-trait + +// docs:start:derive_eq +comptime fn derive_eq(s: StructDefinition) -> Quoted { + let signature = quote { fn eq(_self: Self, _other: Self) -> bool }; + let for_each_field = |name| quote { (_self.$name == _other.$name) }; + let body = |fields| { + if s.fields_as_written().len() == 0 { + quote { true } + } else { + fields + } + }; + crate::meta::make_trait_impl( + s, + quote { Eq }, + signature, + for_each_field, + quote { & }, + body, + ) +} +// docs:end:derive_eq + +impl Eq for Field { + fn eq(self, other: Field) -> 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 u16 { + fn eq(self, other: u16) -> 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 i16 { + fn eq(self, other: i16) -> bool { + self == other + } +} +impl Eq for i32 { + fn eq(self, other: i32) -> bool { + self == other + } +} +impl Eq for i64 { + fn eq(self, other: i64) -> bool { + self == other + } +} + +impl Eq for () { + fn eq(_self: Self, _other: ()) -> bool { + true + } +} +impl Eq for bool { + fn eq(self, other: bool) -> bool { + self == other + } +} + +impl Eq for [T; N] +where + T: Eq, +{ + fn eq(self, other: [T; N]) -> bool { + let mut result = true; + for i in 0..self.len() { + result &= self[i].eq(other[i]); + } + result + } +} + +impl Eq for [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(); + let other_bytes = other.as_bytes(); + self_bytes == other_bytes + } +} + +impl Eq for (A, B) +where + A: Eq, + B: Eq, +{ + fn eq(self, other: (A, B)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) + } +} + +impl Eq for (A, B, C) +where + A: Eq, + B: Eq, + C: Eq, +{ + fn eq(self, other: (A, B, C)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) + } +} + +impl Eq for (A, B, C, D) +where + A: Eq, + B: Eq, + C: Eq, + D: Eq, +{ + fn eq(self, other: (A, B, C, D)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) + } +} + +impl Eq for (A, B, C, D, E) +where + A: Eq, + B: Eq, + C: Eq, + D: Eq, + E: Eq, +{ + fn eq(self, other: (A, B, C, D, E)) -> bool { + self.0.eq(other.0) + & self.1.eq(other.1) + & self.2.eq(other.2) + & self.3.eq(other.3) + & self.4.eq(other.4) + } +} + +impl Eq for Ordering { + fn eq(self, other: Ordering) -> bool { + self.result == other.result + } +} + +// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct +// that has 3 public functions for constructing the struct. +pub struct Ordering { + result: Field, +} + +impl Ordering { + // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built + // into the compiler, do not change these without also updating + // the compiler itself! + pub fn less() -> Ordering { + Ordering { result: 0 } + } + + pub fn equal() -> Ordering { + Ordering { result: 1 } + } + + pub fn greater() -> Ordering { + Ordering { result: 2 } + } +} + +#[derive_via(derive_ord)] +// docs:start:ord-trait +pub trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +// docs:end:ord-trait + +// docs:start:derive_ord +comptime fn derive_ord(s: StructDefinition) -> Quoted { + let signature = quote { fn cmp(_self: Self, _other: Self) -> std::cmp::Ordering }; + let for_each_field = |name| quote { + if result == std::cmp::Ordering::equal() { + result = _self.$name.cmp(_other.$name); + } + }; + let body = |fields| quote { + let mut result = std::cmp::Ordering::equal(); + $fields + result + }; + crate::meta::make_trait_impl(s, quote { Ord }, signature, for_each_field, quote {}, body) +} +// docs:end:derive_ord + +// Note: Field deliberately does not implement Ord + +impl Ord for u64 { + fn cmp(self, other: u64) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for u32 { + fn cmp(self, other: u32) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for u16 { + fn cmp(self, other: u16) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for u8 { + fn cmp(self, other: u8) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for i8 { + fn cmp(self, other: i8) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for i16 { + fn cmp(self, other: i16) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for i32 { + fn cmp(self, other: i32) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for i64 { + fn cmp(self, other: i64) -> Ordering { + if self < other { + Ordering::less() + } else if self > other { + Ordering::greater() + } else { + Ordering::equal() + } + } +} + +impl Ord for () { + fn cmp(_self: Self, _other: ()) -> Ordering { + Ordering::equal() + } +} + +impl Ord for bool { + fn cmp(self, other: bool) -> Ordering { + if self { + if other { + Ordering::equal() + } else { + Ordering::greater() + } + } else if other { + Ordering::less() + } else { + Ordering::equal() + } + } +} + +impl Ord for [T; N] +where + T: Ord, +{ + // The first non-equal element of both arrays determines + // the ordering for the whole array. + fn cmp(self, other: [T; N]) -> Ordering { + let mut result = Ordering::equal(); + 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 [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); + + if result != Ordering::equal() { + result + } else { + self.1.cmp(other.1) + } + } +} + +impl Ord for (A, B, C) +where + A: Ord, + B: Ord, + C: Ord, +{ + fn cmp(self, other: (A, B, C)) -> Ordering { + let mut result = self.0.cmp(other.0); + + if result == Ordering::equal() { + result = self.1.cmp(other.1); + } + + if result == Ordering::equal() { + result = self.2.cmp(other.2); + } + + result + } +} + +impl Ord for (A, B, C, D) +where + A: Ord, + B: Ord, + C: Ord, + D: Ord, +{ + fn cmp(self, other: (A, B, C, D)) -> Ordering { + let mut result = self.0.cmp(other.0); + + if result == Ordering::equal() { + result = self.1.cmp(other.1); + } + + if result == Ordering::equal() { + result = self.2.cmp(other.2); + } + + if result == Ordering::equal() { + result = self.3.cmp(other.3); + } + + result + } +} + +impl Ord for (A, B, C, D, E) +where + A: Ord, + B: Ord, + C: Ord, + D: Ord, + E: Ord, +{ + fn cmp(self, other: (A, B, C, D, E)) -> Ordering { + let mut result = self.0.cmp(other.0); + + if result == Ordering::equal() { + result = self.1.cmp(other.1); + } + + if result == Ordering::equal() { + result = self.2.cmp(other.2); + } + + if result == Ordering::equal() { + result = self.3.cmp(other.3); + } + + if result == Ordering::equal() { + result = self.4.cmp(other.4); + } + + 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::{max, min}; + + #[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 new file mode 100644 index 00000000000..7aed5e6a0e4 --- /dev/null +++ b/noir_stdlib/src/collections/bounded_vec.nr @@ -0,0 +1,692 @@ +use crate::{cmp::Eq, convert::From}; + +/// 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: +/// +/// ```noir +/// let mut vector: BoundedVec = BoundedVec::new(); +/// for i in 0..5 { +/// vector.push(i); +/// } +/// assert(vector.len() == 5); +/// assert(vector.max_len() == 10); +/// ``` +pub struct BoundedVec { + storage: [T; MaxLen], + len: u32, +} + +impl BoundedVec { + /// 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: + /// + /// ```noir + /// 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: + /// + /// ```noir + /// fn good() -> 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 `good`'s return value + /// v2 + /// } + /// + /// fn bad() { + /// // Error: Type annotation needed + /// // The compiler can't infer `MaxLen` from the following code: + /// let mut v3 = BoundedVec::new(); + /// v3.push(5); + /// } + /// ``` + /// + /// 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. + pub fn new() -> Self { + let zeroed = crate::mem::zeroed(); + BoundedVec { storage: [zeroed; MaxLen], len: 0 } + } + + /// 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: + /// + /// ```noir + /// fn foo(v: BoundedVec) { + /// let first = v.get(0); + /// let last = v.get(v.len() - 1); + /// assert(first != last); + /// } + /// ``` + pub fn get(self, index: u32) -> T { + assert(index < self.len, "Attempted to read past end of BoundedVec"); + self.get_unchecked(index) + } + + /// 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: + /// + /// ```noir + /// 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 + /// } + /// ``` + pub fn get_unchecked(self, index: u32) -> T { + self.storage[index] + } + + /// Writes an element to 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: + /// + /// ```noir + /// fn foo(v: BoundedVec) { + /// let first = v.get(0); + /// assert(first != 42); + /// v.set(0, 42); + /// let new_first = v.get(0); + /// assert(new_first == 42); + /// } + /// ``` + pub fn set(&mut self, index: u32, value: T) { + assert(index < self.len, "Attempted to write past end of BoundedVec"); + self.set_unchecked(index, value) + } + + /// Writes an element to 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: + /// + /// ```noir + /// fn set_unchecked_example() { + /// let mut vec: BoundedVec = BoundedVec::new(); + /// vec.extend_from_array([1, 2]); + /// + /// // Here we're safely writing within the valid range of `vec` + /// // `vec` now has the value [42, 2] + /// vec.set_unchecked(0, 42); + /// + /// // We can then safely read this value back out of `vec`. + /// // Notice that we use the checked version of `get` which would prevent reading unsafe values. + /// assert_eq(vec.get(0), 42); + /// + /// // We've now written past the end of `vec`. + /// // As this index is still within the maximum potential length of `v`, + /// // it won't cause a constraint failure. + /// vec.set_unchecked(2, 42); + /// println(vec); + /// + /// // This will write past the end of the maximum potential length of `vec`, + /// // it will then trigger a constraint failure. + /// vec.set_unchecked(5, 42); + /// println(vec); + /// } + /// ``` + pub fn set_unchecked(&mut self, index: u32, value: T) { + self.storage[index] = value; + } + + /// 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: + /// + /// ```noir + /// let mut v: BoundedVec = BoundedVec::new(); + /// + /// v.push(1); + /// v.push(2); + /// + /// // Panics with failed assertion "push out of bounds" + /// v.push(3); + /// ``` + pub fn push(&mut self, elem: T) { + assert(self.len < MaxLen, "push out of bounds"); + + self.storage[self.len] = elem; + self.len += 1; + } + + /// Returns the current length of this vector + /// + /// Example: + /// + /// ```noir + /// 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); + /// ``` + pub fn len(self) -> u32 { + self.len + } + + /// Returns the maximum length of this vector. This is always + /// equal to the `MaxLen` parameter this vector was initialized with. + /// + /// Example: + /// + /// ```noir + /// let mut v: BoundedVec = BoundedVec::new(); + /// + /// assert(v.max_len() == 5); + /// v.push(10); + /// assert(v.max_len() == 5); + /// ``` + pub fn max_len(_self: BoundedVec) -> u32 { + 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: + /// + /// ```noir + /// 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]); + /// ``` + pub fn storage(self) -> [T; MaxLen] { + self.storage + } + + /// 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: + /// + /// ```noir + /// 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); + /// ``` + pub fn extend_from_array(&mut self, array: [T; Len]) { + let new_len = self.len + array.len(); + 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; + } + + /// Pushes each element from the given slice to this vector. + /// + /// Panics if pushing each element would cause the length of this vector + /// to exceed the maximum length. + /// + /// Example: + /// + /// ```noir + /// let mut vec: BoundedVec = BoundedVec::new(); + /// vec.extend_from_slice(&[2, 4]); + /// + /// assert(vec.len == 2); + /// assert(vec.get(0) == 2); + /// assert(vec.get(1) == 4); + /// ``` + 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; + } + + /// 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. + /// + /// ```noir + /// 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]); + /// ``` + 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 <= MaxLen, "extend_from_bounded_vec out of bounds"); + + let mut exceeded_len = false; + for i in 0..Len { + exceeded_len |= i == append_len; + if !exceeded_len { + self.storage[self.len + i] = vec.get_unchecked(i); + } + } + self.len = new_len; + } + + /// 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: + /// + /// ```noir + /// let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3]) + /// ``` + 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 + } + + /// 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: + /// + /// ```noir + /// 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(); + /// ``` + pub fn pop(&mut self) -> T { + assert(self.len > 0); + self.len -= 1; + + let elem = self.storage[self.len]; + self.storage[self.len] = crate::mem::zeroed(); + elem + } + + /// Returns true if the given predicate returns true for any element + /// in this vector. + /// + /// Example: + /// + /// ```noir + /// 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); + /// ``` + pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { + let mut ret = false; + let mut exceeded_len = false; + for i in 0..MaxLen { + exceeded_len |= i == self.len; + if !exceeded_len { + ret |= predicate(self.storage[i]); + } + } + ret + } + + /// Creates a new vector of equal size by calling a closure on each element in this vector. + /// + /// Example: + /// + /// ```noir + /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + /// let result = vec.map(|value| value * 2); + /// + /// let expected = BoundedVec::from_array([2, 4, 6, 8]); + /// assert_eq(result, expected); + /// ``` + pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec { + let mut ret = BoundedVec::new(); + ret.len = self.len(); + for i in 0..MaxLen { + if i < self.len() { + ret.storage[i] = f(self.get_unchecked(i)); + } + } + ret + } + + /// Creates a new BoundedVec from the given array and length. + /// The given length must be less than or equal to the length of the array. + /// + /// This function will zero out any elements at or past index `len` of `array`. + /// This incurs an extra runtime cost of O(MaxLen). If you are sure your array is + /// zeroed after that index, you can use `from_parts_unchecked` to remove the extra loop. + /// + /// Example: + /// + /// ```noir + /// let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3); + /// assert_eq(vec.len(), 3); + /// ``` + pub fn from_parts(mut array: [T; MaxLen], len: u32) -> Self { + assert(len <= MaxLen); + let zeroed = crate::mem::zeroed(); + for i in 0..MaxLen { + if i >= len { + array[i] = zeroed; + } + } + BoundedVec { storage: array, len } + } + + /// Creates a new BoundedVec from the given array and length. + /// The given length must be less than or equal to the length of the array. + /// + /// This function is unsafe because it expects all elements past the `len` index + /// of `array` to be zeroed, but does not check for this internally. Use `from_parts` + /// for a safe version of this function which does zero out any indices past the + /// given length. Invalidating this assumption can notably cause `BoundedVec::eq` + /// to give incorrect results since it will check even elements past `len`. + /// + /// Example: + /// + /// ```noir + /// let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3); + /// assert_eq(vec.len(), 3); + /// + /// // invalid use! + /// let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3); + /// let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3); + /// + /// // both vecs have length 3 so we'd expect them to be equal, but this + /// // fails because elements past the length are still checked in eq + /// assert_eq(vec1, vec2); // fails + /// ``` + pub fn from_parts_unchecked(array: [T; MaxLen], len: u32) -> Self { + assert(len <= MaxLen); + BoundedVec { storage: array, len } + } +} + +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. + if self.len == other.len { + self.storage == other.storage + } else { + false + } + } +} + +impl From<[T; Len]> for BoundedVec { + fn from(array: [T; Len]) -> BoundedVec { + BoundedVec::from_array(array) + } +} + +mod bounded_vec_tests { + + mod get { + use crate::collections::bounded_vec::BoundedVec; + + #[test(should_fail_with = "Attempted to read past end of BoundedVec")] + fn panics_when_reading_elements_past_end_of_vec() { + let vec: BoundedVec = BoundedVec::new(); + + crate::println(vec.get(0)); + } + } + + mod set { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn set_updates_values_properly() { + let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]); + + vec.set(0, 42); + assert_eq(vec.storage, [42, 0, 0, 0, 0]); + + vec.set(1, 43); + assert_eq(vec.storage, [42, 43, 0, 0, 0]); + + vec.set(2, 44); + assert_eq(vec.storage, [42, 43, 44, 0, 0]); + + vec.set(1, 10); + assert_eq(vec.storage, [42, 10, 44, 0, 0]); + + vec.set(0, 0); + assert_eq(vec.storage, [0, 10, 44, 0, 0]); + } + + #[test(should_fail_with = "Attempted to write past end of BoundedVec")] + fn panics_when_writing_elements_past_end_of_vec() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.set(0, 42); + + // Need to use println to avoid DIE removing the write operation. + crate::println(vec.get(0)); + } + } + + mod map { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn applies_function_correctly() { + // docs:start:bounded-vec-map-example + let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| value * 2); + // docs:end:bounded-vec-map-example + let expected = BoundedVec::from_array([2, 4, 6, 8]); + + assert_eq(result, expected); + } + + #[test] + fn applies_function_that_changes_return_type() { + let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| (value * 2) as Field); + let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]); + + assert_eq(result, expected); + } + + #[test] + fn does_not_apply_function_past_len() { + let vec: BoundedVec = BoundedVec::from_array([0, 1]); + let result = vec.map(|value| if value == 0 { 5 } else { value }); + let expected = BoundedVec::from_array([5, 1]); + + assert_eq(result, expected); + assert_eq(result.get_unchecked(2), 0); + } + } + + 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.get(0), 1); + assert_eq(bounded_vec.get(1), 2); + assert_eq(bounded_vec.get(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; + use crate::convert::From; + + #[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.get(0), 1); + assert_eq(bounded_vec.get(1), 2); + } + } + + mod trait_eq { + 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_parts { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn from_parts() { + // docs:start:from-parts + let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3); + assert_eq(vec.len(), 3); + + // Any elements past the given length are zeroed out, so these + // two BoundedVecs will be completely equal + let vec1: BoundedVec = BoundedVec::from_parts([1, 2, 3, 1], 3); + let vec2: BoundedVec = BoundedVec::from_parts([1, 2, 3, 2], 3); + assert_eq(vec1, vec2); + // docs:end:from-parts + } + + #[test] + fn from_parts_unchecked() { + // docs:start:from-parts-unchecked + let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3); + assert_eq(vec.len(), 3); + + // invalid use! + let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3); + let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3); + + // both vecs have length 3 so we'd expect them to be equal, but this + // fails because elements past the length are still checked in eq + assert(vec1 != vec2); + // docs:end:from-parts-unchecked + } + } +} diff --git a/noir_stdlib/src/collections/map.nr b/noir_stdlib/src/collections/map.nr new file mode 100644 index 00000000000..bc0b80124db --- /dev/null +++ b/noir_stdlib/src/collections/map.nr @@ -0,0 +1,708 @@ +use crate::cmp::Eq; +use crate::collections::bounded_vec::BoundedVec; +use crate::default::Default; +use crate::hash::{BuildHasher, Hash, Hasher}; +use crate::option::Option; + +// We use load factor alpha_max = 0.75. +// Upon exceeding it, assert will fail in order to inform the user +// about performance degradation, so that he can adjust the capacity. +global MAX_LOAD_FACTOR_NUMERATOR: u32 = 3; +global MAX_LOAD_FACTOR_DEN0MINATOR: u32 = 4; + +/// `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`. +/// +/// Example: +/// +/// ```noir +/// // Create a mapping from Fields to u32s with a maximum length of 12 +/// // using a poseidon2 hasher +/// use std::hash::poseidon2::Poseidon2Hasher; +/// let mut map: HashMap> = HashMap::default(); +/// +/// map.insert(1, 2); +/// map.insert(3, 4); +/// +/// let two = map.get(1).unwrap(); +/// ``` +pub struct HashMap { + _table: [Slot; N], + + /// Amount of valid elements in the map. + _len: u32, + + _build_hasher: B, +} + +// Data unit in the HashMap table. +// In case Noir adds support for enums in the future, this +// should be refactored to have three states: +// 1. (key, value) +// 2. (empty) +// 3. (deleted) +struct Slot { + _key_value: Option<(K, V)>, + _is_deleted: bool, +} + +impl Default for Slot { + fn default() -> Self { + Slot { _key_value: Option::none(), _is_deleted: false } + } +} + +impl Slot { + fn is_valid(self) -> bool { + !self._is_deleted & self._key_value.is_some() + } + + fn is_available(self) -> bool { + self._is_deleted | self._key_value.is_none() + } + + fn key_value(self) -> Option<(K, V)> { + self._key_value + } + + fn key_value_unchecked(self) -> (K, V) { + self._key_value.unwrap_unchecked() + } + + fn set(&mut self, key: K, value: V) { + self._key_value = Option::some((key, value)); + self._is_deleted = false; + } + + // Shall not override `_key_value` with Option::none(), + // because we must be able to differentiate empty + // and deleted slots for lookup. + fn mark_deleted(&mut self) { + self._is_deleted = true; + } +} + +// While conducting lookup, we iterate attempt from 0 to N - 1 due to heuristic, +// that if we have went that far without finding desired, +// it is very unlikely to be after - performance will be heavily degraded. +impl HashMap { + /// Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple + /// hashmaps are created with the same hasher instance. + /// + /// Example: + /// + /// ```noir + /// let my_hasher: BuildHasherDefault = Default::default(); + /// let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + /// assert(hashmap.is_empty()); + /// ``` + // 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 hashmap, removing all key-value pairs from it. + /// + /// Example: + /// + /// ```noir + /// assert(!map.is_empty()); + /// map.clear(); + /// assert(map.is_empty()); + /// ``` + // docs:start:clear + pub fn clear(&mut self) { + // docs:end:clear + self._table = [Slot::default(); N]; + self._len = 0; + } + + /// Returns `true` if the hashmap contains the given key. Unlike `get`, this will not also return + /// the value associated with the key. + /// + /// Example: + /// + /// ```noir + /// if map.contains_key(7) { + /// let value = map.get(7); + /// assert(value.is_some()); + /// } else { + /// println("No value for key 7!"); + /// } + /// ``` + // docs:start:contains_key + pub fn contains_key(self, key: K) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher, + { + // docs:end:contains_key + self.get(key).is_some() + } + + /// Returns `true` if the length of the hash map is empty. + /// + /// Example: + /// + /// ```noir + /// assert(map.is_empty()); + /// + /// map.insert(1, 2); + /// assert(!map.is_empty()); + /// + /// map.remove(1); + /// assert(map.is_empty()); + /// ``` + // docs:start:is_empty + pub fn is_empty(self) -> bool { + // docs:end:is_empty + self._len == 0 + } + + /// 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: + /// + /// ```noir + /// 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: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() { + // 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 self_len = self._len; + let entries_len = entries.len(); + let msg = + f"Amount of valid elements should have been {self_len} times, but got {entries_len}."; + assert(entries.len() == self._len, msg); + + entries + } + + /// 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: + /// + /// ```noir + /// 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: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.push(key); + } + } + + let self_len = self._len; + let keys_len = keys.len(); + let msg = + f"Amount of valid elements should have been {self_len} times, but got {keys_len}."; + assert(keys.len() == self._len, msg); + + keys + } + + /// 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: + /// + /// ```noir + /// 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: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) = slot.key_value_unchecked(); + values.push(value); + } + } + + let self_len = self._len; + let values_len = values.len(); + let msg = + f"Amount of valid elements should have been {self_len} times, but got {values_len}."; + assert(values.len() == self._len, msg); + + values + } + + /// 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: + /// + /// ```noir + /// // 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:start:iter_mut + pub fn iter_mut(&mut self, f: fn(K, V) -> (K, V)) + where + 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.get_unchecked(i); + let (key, value) = f(entry.0, entry.1); + new_map.insert(key, value); + } + } + + self._table = new_map._table; + } + + /// 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: + /// + /// ```noir + /// // Double each key, leaving the value associated with that key untouched + /// map.iter_keys_mut(|k| k * 2); + /// ``` + // docs:start:iter_keys_mut + pub fn iter_keys_mut(&mut self, f: fn(K) -> K) + where + 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.get_unchecked(i); + let (key, value) = (f(entry.0), entry.1); + new_map.insert(key, value); + } + } + + self._table = new_map._table; + } + + /// 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: + /// + /// ```noir + /// // Halve each value + /// map.iter_values_mut(|v| v / 2); + /// ``` + // 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() { + let (key, value) = slot.key_value_unchecked(); + slot.set(key, f(value)); + self._table[i] = slot; + } + } + } + + /// 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: + /// + /// ```noir + /// map.retain(|k, v| (k != 0) & (v != 0)); + /// ``` + // 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() { + let (key, value) = slot.key_value_unchecked(); + if !f(key, value) { + slot.mark_deleted(); + self._len -= 1; + self._table[index] = slot; + } + } + } + } + + /// Returns the current length of this hash map. + /// + /// Example: + /// + /// ```noir + /// // 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:start:len + pub fn len(self) -> u32 { + // docs:end:len + self._len + } + + /// 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: + /// + /// ```noir + /// let empty_map: HashMap> = HashMap::default(); + /// assert(empty_map.len() == 0); + /// assert(empty_map.capacity() == 42); + /// ``` + // docs:start:capacity + pub fn capacity(_self: Self) -> u32 { + // docs:end:capacity + N + } + + /// Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + /// + /// Example: + /// + /// ```noir + /// fn get_example(map: HashMap>) { + /// let x = map.get(12); + /// + /// if x.is_some() { + /// assert(x.unwrap() == 42); + /// } + /// } + /// ``` + // docs:start:get + pub fn get(self, key: K) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher, + { + // docs:end:get + let mut result = Option::none(); + + let hash = self.hash(key); + let mut should_break = false; + + for attempt in 0..N { + 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. + if slot.is_valid() { + let (current_key, value) = slot.key_value_unchecked(); + if current_key == key { + result = Option::some(value); + should_break = true; + } + } + } + } + + result + } + + /// 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: + /// + /// ```noir + /// let mut map: HashMap> = HashMap::default(); + /// map.insert(12, 42); + /// assert(map.len() == 1); + /// ``` + // docs:start:insert + pub fn insert(&mut self, key: K, value: V) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher, + { + // docs:end:insert + self.assert_load_factor(); + + let hash = self.hash(key); + let mut should_break = false; + + for attempt in 0..N { + if !should_break { + let index = self.quadratic_probe(hash, attempt as u32); + let mut slot = self._table[index]; + let mut insert = false; + + // Either marked as deleted or has unset key-value. + if slot.is_available() { + insert = true; + self._len += 1; + } else { + let (current_key, _) = slot.key_value_unchecked(); + if current_key == key { + insert = true; + } + } + + if insert { + slot.set(key, value); + self._table[index] = slot; + should_break = true; + } + } + } + } + + /// Removes the given key-value pair from the map. If the key was not already present + /// in the map, this does nothing. + /// + /// Example: + /// + /// ```noir + /// let mut map: HashMap> = HashMap::default(); + /// map.insert(12, 42); + /// assert(!map.is_empty()); + /// + /// 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:start:remove + pub fn remove(&mut self, key: K) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher, + { + // docs:end:remove + let hash = self.hash(key); + let mut should_break = false; + + for attempt in 0..N { + 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. + if slot.is_valid() { + let (current_key, _) = slot.key_value_unchecked(); + if current_key == key { + slot.mark_deleted(); + self._table[index] = slot; + self._len -= 1; + should_break = true; + } + } + } + } + } + + // Apply HashMap's hasher onto key to obtain pre-hash for probing. + fn hash(self, key: K) -> u32 + where + K: Hash, + B: BuildHasher, + H: Hasher, + { + let mut hasher = self._build_hasher.build_hasher(); + key.hash(&mut hasher); + 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: u32, attempt: u32) -> u32 { + (hash + (attempt + attempt * attempt) / 2) % N + } + + // Amount of elements in the table in relation to available slots exceeds alpha_max. + // To avoid a comparatively more expensive division operation + // we conduct cross-multiplication instead. + // n / m >= MAX_LOAD_FACTOR_NUMERATOR / MAX_LOAD_FACTOR_DEN0MINATOR + // n * MAX_LOAD_FACTOR_DEN0MINATOR >= m * MAX_LOAD_FACTOR_NUMERATOR + fn assert_load_factor(self) { + let lhs = self._len * MAX_LOAD_FACTOR_DEN0MINATOR; + let rhs = self._table.len() * MAX_LOAD_FACTOR_NUMERATOR; + let exceeded = lhs >= rhs; + assert(!exceeded, "Load factor is exceeded, consider increasing the capacity."); + } +} + +// 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, + V: Eq, + B: BuildHasher, + H: Hasher, +{ + /// Checks if two HashMaps are equal. + /// + /// Example: + /// + /// ```noir + /// 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); + /// ``` + fn eq(self, other: HashMap) -> bool { + // docs:end:eq + let mut equal = false; + + if self.len() == other.len() { + equal = true; + for slot in self._table { + // Not marked as deleted and has key-value. + if equal & slot.is_valid() { + let (key, value) = slot.key_value_unchecked(); + let other_value = other.get(key); + + if other_value.is_none() { + equal = false; + } else { + let other_value = other_value.unwrap_unchecked(); + if value != other_value { + equal = false; + } + } + } + } + } + + equal + } +} + +// docs:start:default +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default, +{ + /// Constructs an empty HashMap. + /// + /// Example: + /// + /// ```noir + /// let hashmap: HashMap> = HashMap::default(); + /// assert(hashmap.is_empty()); + /// ``` + 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/mod.nr b/noir_stdlib/src/collections/mod.nr new file mode 100644 index 00000000000..d11e9f2febb --- /dev/null +++ b/noir_stdlib/src/collections/mod.nr @@ -0,0 +1,4 @@ +pub mod vec; +pub mod bounded_vec; +pub mod map; +pub mod umap; diff --git a/noir_stdlib/src/collections/umap.nr b/noir_stdlib/src/collections/umap.nr new file mode 100644 index 00000000000..bcb9759b4db --- /dev/null +++ b/noir_stdlib/src/collections/umap.nr @@ -0,0 +1,465 @@ +use crate::cmp::Eq; +use crate::default::Default; +use crate::hash::{BuildHasher, Hash, Hasher}; +use crate::option::Option; + +// An unconstrained hash table with open addressing and quadratic probing. +// Note that "unconstrained" here means that almost all operations on this +// map are unconstrained and importantly are not constrained afterward either. +// This map is meant to be used in unconstrained or comptime code where this +// is not an issue. +// +// Compared to the constrained HashMap type, UHashMap can grow automatically +// as needed and is more efficient since it can break out of loops early. +pub struct UHashMap { + _table: [Slot], + + // Amount of valid elements in the map. + _len: u32, + + _build_hasher: B, +} + +// Data unit in the UHashMap table. +// In case Noir adds support for enums in the future, this +// should be refactored to have three states: +// 1. (key, value) +// 2. (empty) +// 3. (deleted) +struct Slot { + _key_value: Option<(K, V)>, + _is_deleted: bool, +} + +impl Default for Slot { + fn default() -> Self { + Slot { _key_value: Option::none(), _is_deleted: false } + } +} + +impl Slot { + fn is_valid(self) -> bool { + !self._is_deleted & self._key_value.is_some() + } + + fn is_available(self) -> bool { + self._is_deleted | self._key_value.is_none() + } + + fn key_value(self) -> Option<(K, V)> { + self._key_value + } + + fn key_value_unchecked(self) -> (K, V) { + self._key_value.unwrap_unchecked() + } + + fn set(&mut self, key: K, value: V) { + self._key_value = Option::some((key, value)); + self._is_deleted = false; + } + + // Shall not override `_key_value` with Option::none(), + // because we must be able to differentiate empty + // and deleted slots for lookup. + fn mark_deleted(&mut self) { + self._is_deleted = true; + } +} + +// While conducting lookup, we iterate attempt from 0 to N - 1 due to heuristic, +// that if we have went that far without finding desired, +// it is very unlikely to be after - performance will be heavily degraded. +impl UHashMap { + // Creates a new instance of UHashMap 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()]; + let _len = 0; + Self { _table, _len, _build_hasher } + } + + pub fn with_hasher_and_capacity(_build_hasher: B, capacity: u32) -> Self + where + B: BuildHasher, + { + // docs:end:with_hasher + let mut _table = &[]; + for _ in 0..capacity { + _table = _table.push_back(Slot::default()); + } + 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()]; + 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) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher, + { + // docs:end:contains_key + /// Safety: unconstrained context + unsafe { 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 + } + + // Returns a BoundedVec of all valid entries in this UHashMap. + // The length of the returned vector will always match the length of this UHashMap. + // docs:start:entries + pub fn entries(self) -> [(K, V)] { + // docs:end:entries + let mut entries = &[]; + + for slot in self._table { + if slot.is_valid() { + // SAFETY: slot.is_valid() should ensure there is a valid key-value pairing here + let key_value = slot.key_value().unwrap_unchecked(); + entries = entries.push_back(key_value); + } + } + + let self_len = self._len; + let entries_len = entries.len(); + let msg = + f"Amount of valid elements should have been {self_len} times, but got {entries_len}."; + assert(entries.len() == self._len, msg); + + entries + } + + // Returns a BoundedVec containing all the keys within this UHashMap. + // The length of the returned vector will always match the length of this UHashMap. + // docs:start:keys + pub fn keys(self) -> [K] { + // docs:end:keys + let mut keys = &[]; + + for slot in self._table { + if slot.is_valid() { + let (key, _) = slot.key_value_unchecked(); + keys = keys.push_back(key); + } + } + + let self_len = self._len; + let keys_len = keys.len(); + let msg = + f"Amount of valid elements should have been {self_len} times, but got {keys_len}."; + assert(keys.len() == self._len, msg); + + keys + } + + // Returns a BoundedVec containing all the values within this UHashMap. + // The length of the returned vector will always match the length of this UHashMap. + // docs:start:values + pub fn values(self) -> [V] { + // docs:end:values + let mut values = &[]; + + for slot in self._table { + if slot.is_valid() { + let (_, value) = slot.key_value_unchecked(); + values = values.push_back(value); + } + } + + let self_len = self._len; + let values_len = values.len(); + 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 unconstrained fn iter_mut(&mut self, f: fn(K, V) -> (K, V)) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher, + { + // docs:end:iter_mut + let mut entries = self.entries(); + let mut new_map = UHashMap::with_hasher(self._build_hasher); + + for entry in entries { + let (key, value) = f(entry.0, entry.1); + new_map.insert(key, value); + } + + self._table = new_map._table; + } + + // For each key applies mutator function. + // docs:start:iter_keys_mut + pub unconstrained fn iter_keys_mut(&mut self, f: fn(K) -> K) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher, + { + // docs:end:iter_keys_mut + let mut entries = self.entries(); + let mut new_map = UHashMap::with_hasher(self._build_hasher); + + for entry in entries { + let (key, value) = (f(entry.0), entry.1); + new_map.insert(key, value); + } + + self._table = new_map._table; + } + + // 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..self._table.len() { + let mut slot = self._table[i]; + if slot.is_valid() { + let (key, value) = slot.key_value_unchecked(); + slot.set(key, f(value)); + self._table[i] = slot; + } + } + } + + // 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..self._table.len() { + let mut slot = self._table[index]; + if slot.is_valid() { + let (key, value) = slot.key_value_unchecked(); + if !f(key, value) { + slot.mark_deleted(); + self._len -= 1; + self._table[index] = slot; + } + } + } + } + + // Amount of active key-value entries. + // docs:start:len + pub fn len(self) -> u32 { + // docs:end:len + self._len + } + + // Get the current capacity of the inner table. + // docs:start:capacity + pub fn capacity(self: Self) -> u32 { + // docs:end:capacity + self._table.len() + } + + // Get the value by key. If it does not exist, returns none(). + // docs:start:get + pub unconstrained fn get(self, key: K) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher, + { + // docs:end:get + let mut result = Option::none(); + + let hash = self.hash(key); + + for attempt in 0..self._table.len() { + let index = self.quadratic_probe(hash, attempt as u32); + let slot = self._table[index]; + + // Not marked as deleted and has key-value. + if slot.is_valid() { + let (current_key, value) = slot.key_value_unchecked(); + if current_key == key { + result = Option::some(value); + break; + } + } + } + + result + } + + // Insert key-value entry. In case key was already present, value is overridden. + // docs:start:insert + pub unconstrained fn insert(&mut self, key: K, value: V) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher, + { + // docs:end:insert + self.try_resize(); + + let hash = self.hash(key); + + for attempt in 0..self._table.len() { + let index = self.quadratic_probe(hash, attempt as u32); + let mut slot = self._table[index]; + let mut insert = false; + + // Either marked as deleted or has unset key-value. + if slot.is_available() { + insert = true; + self._len += 1; + } else { + let (current_key, _) = slot.key_value_unchecked(); + if current_key == key { + insert = true; + } + } + + if insert { + slot.set(key, value); + self._table[index] = slot; + break; + } + } + } + + unconstrained fn try_resize(&mut self) + where + B: BuildHasher, + K: Eq + Hash, + H: Hasher, + { + if self.len() + 1 >= self.capacity() / 2 { + let capacity = self.capacity() * 2; + let mut new_map = UHashMap::with_hasher_and_capacity(self._build_hasher, capacity); + + for entry in self.entries() { + new_map.insert(entry.0, entry.1); + } + *self = new_map; + } + } + + // Removes a key-value entry. If key is not present, UHashMap remains unchanged. + // docs:start:remove + pub unconstrained fn remove(&mut self, key: K) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher, + { + // docs:end:remove + let hash = self.hash(key); + + for attempt in 0..self._table.len() { + let index = self.quadratic_probe(hash, attempt as u32); + let mut slot = self._table[index]; + + // Not marked as deleted and has key-value. + if slot.is_valid() { + let (current_key, _) = slot.key_value_unchecked(); + if current_key == key { + slot.mark_deleted(); + self._table[index] = slot; + self._len -= 1; + break; + } + } + } + } + + // Apply UHashMap's hasher onto key to obtain pre-hash for probing. + fn hash(self, key: K) -> u32 + where + K: Hash, + B: BuildHasher, + H: Hasher, + { + let mut hasher = self._build_hasher.build_hasher(); + key.hash(&mut hasher); + 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: u32, attempt: u32) -> u32 { + (hash + (attempt + attempt * attempt) / 2) % self._table.len() + } +} + +// Equality class on UHashMap 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 UHashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher, +{ + fn eq(self, other: UHashMap) -> bool { + // docs:end:eq + let mut equal = false; + + if self.len() == other.len() { + equal = true; + for slot in self._table { + // Not marked as deleted and has key-value. + if equal & slot.is_valid() { + let (key, value) = slot.key_value_unchecked(); + /// Safety: unconstrained context + let other_value = unsafe { other.get(key) }; + + if other_value.is_none() { + equal = false; + } else { + let other_value = other_value.unwrap_unchecked(); + if value != other_value { + equal = false; + } + } + } + } + } + + equal + } +} + +// docs:start:default +impl Default for UHashMap +where + B: BuildHasher + Default, + H: Hasher + Default, +{ + fn default() -> Self { + // docs:end:default + UHashMap::with_hasher(B::default()) + } +} diff --git a/noir_stdlib/src/collections/vec.nr b/noir_stdlib/src/collections/vec.nr new file mode 100644 index 00000000000..aa019095683 --- /dev/null +++ b/noir_stdlib/src/collections/vec.nr @@ -0,0 +1,98 @@ +pub struct Vec { + pub(crate) slice: [T], +} +// A mutable vector type implemented as a wrapper around immutable slices. +// A separate type is technically not needed but helps differentiate which operations are mutable. +impl Vec { + pub fn new() -> Self { + Self { slice: &[] } + } + + // Create a Vec containing each element from the given slice. + // Mutations to the resulting Vec will not affect the original slice. + pub fn from_slice(slice: [T]) -> Self { + Self { slice } + } + + /// 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: u32) -> T { + self.slice[index] + } + + /// Write an element to the vector at the given index. + /// Panics if the given index points beyond the end of the vector (`self.len()`). + pub fn set(&mut self, index: u32, value: T) { + self.slice[index] = value; + } + + /// Push a new element to the end of the vector, returning a + /// new vector with a length one greater than the + /// original unmodified vector. + pub fn push(&mut self, elem: T) { + self.slice = self.slice.push_back(elem); + } + + /// Pop an element from the end of the given vector, returning + /// a new vector with a length of one less than the given vector, + /// as well as the popped element. + /// Panics if the given vector's length is zero. + pub fn pop(&mut self) -> T { + let (popped_slice, last_elem) = self.slice.pop_back(); + self.slice = popped_slice; + last_elem + } + + /// Insert an element at a specified index, shifting all elements + /// after it to the right + 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: 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) -> u32 { + self.slice.len() + } +} + +mod tests { + use crate::collections::vec::Vec; + + #[test] + fn set_updates_values_properly() { + let mut vec = Vec { slice: &[0, 0, 0, 0, 0] }; + + vec.set(0, 42); + assert_eq(vec.slice, &[42, 0, 0, 0, 0]); + + vec.set(1, 43); + assert_eq(vec.slice, &[42, 43, 0, 0, 0]); + + vec.set(2, 44); + assert_eq(vec.slice, &[42, 43, 44, 0, 0]); + + vec.set(1, 10); + assert_eq(vec.slice, &[42, 10, 44, 0, 0]); + + vec.set(0, 0); + assert_eq(vec.slice, &[0, 10, 44, 0, 0]); + } + + #[test(should_fail)] + fn panics_when_writing_elements_past_end_of_vec() { + let mut vec = Vec::new(); + vec.set(0, 42); + + // Need to use println to avoid DIE removing the write operation. + crate::println(vec.get(0)); + } +} diff --git a/noir_stdlib/src/compat.nr b/noir_stdlib/src/compat.nr new file mode 100644 index 00000000000..c65246816bf --- /dev/null +++ b/noir_stdlib/src/compat.nr @@ -0,0 +1,21 @@ +comptime global BN254_MODULUS_BE_BYTES: [u8] = &[ + 48, 100, 78, 114, 225, 49, 160, 41, 184, 80, 69, 182, 129, 129, 88, 93, 40, 51, 232, 72, 121, + 185, 112, 145, 67, 225, 245, 147, 240, 0, 0, 1, +]; + +pub fn is_bn254() -> bool { + comptime { + // We can't use the `Eq` trait here due to limitations on calling non-comptime functions + // defined within the same crate. + let mut eq = true; + + let modulus_be_bytes = crate::field::modulus_be_bytes(); + // We can't do `BN254_MODULUS_BE_BYTES.len()` due to limitations on calling non-comptime functions. + assert_eq(crate::field::modulus_num_bits(), 254); + for i in 0..32 { + eq &= modulus_be_bytes[i] == BN254_MODULUS_BE_BYTES[i]; + } + + eq + } +} diff --git a/noir_stdlib/src/convert.nr b/noir_stdlib/src/convert.nr new file mode 100644 index 00000000000..1e5c1484b5f --- /dev/null +++ b/noir_stdlib/src/convert.nr @@ -0,0 +1,167 @@ +// docs:start:from-trait +pub trait From { + fn from(input: T) -> Self; +} +// docs:end:from-trait + +impl From for T { + fn from(input: T) -> T { + input + } +} + +// docs:start:into-trait +pub trait Into { + fn into(self) -> T; +} + +impl Into for U +where + T: From, +{ + fn into(self) -> T { + T::from(self) + } +} +// docs:end:into-trait + +// docs:start:from-impls +// 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 + } +} +// docs:end:from-impls + +/// A generic interface for casting between primitive types, +/// equivalent of using the `as` keyword between values. +/// +/// # Example +/// +/// ``` +/// let x: Field = 1234567890; +/// let y: u8 = x as u8; +/// let z: u8 = x.as_(); +/// assert_eq(y, z); +/// ``` +pub trait AsPrimitive { + /// The equivalent of doing `self as T`. + fn as_(self) -> T; +} + +#[generate_as_primitive_impls] +comptime fn generate_as_primitive_impls(_: FunctionDefinition) -> Quoted { + let types = [ + quote { bool }, + quote { u8 }, + quote { u16 }, + quote { u32 }, + quote { u64 }, + quote { i8 }, + quote { i16 }, + quote { i32 }, + quote { i64 }, + quote { Field }, + ]; + + let mut impls = &[]; + for type1 in types { + for type2 in types { + impls = impls.push_back( + quote { + impl AsPrimitive<$type1> for $type2 { + fn as_(self) -> $type1 { + self as $type1 + } + } + }, + ); + } + } + impls.join(quote {}) +} diff --git a/noir_stdlib/src/default.nr b/noir_stdlib/src/default.nr new file mode 100644 index 00000000000..01f10a368b1 --- /dev/null +++ b/noir_stdlib/src/default.nr @@ -0,0 +1,141 @@ +use crate::meta::derive_via; + +#[derive_via(derive_default)] +// docs:start:default-trait +pub trait Default { + fn default() -> Self; +} +// docs:end:default-trait + +comptime fn derive_default(s: StructDefinition) -> Quoted { + let name = quote { Default }; + let signature = quote { fn default() -> Self }; + let for_each_field = |name| quote { $name: Default::default() }; + let body = |fields| quote { Self { $fields } }; + crate::meta::make_trait_impl(s, name, signature, for_each_field, quote { , }, body) +} + +impl Default for Field { + fn default() -> Field { + 0 + } +} + +impl Default for u1 { + fn default() -> u1 { + 0 + } +} +impl Default for u8 { + fn default() -> u8 { + 0 + } +} +impl Default for u16 { + fn default() -> u16 { + 0 + } +} +impl Default for u32 { + fn default() -> u32 { + 0 + } +} +impl Default for u64 { + fn default() -> u64 { + 0 + } +} + +impl Default for i8 { + fn default() -> i8 { + 0 + } +} +impl Default for i16 { + fn default() -> i16 { + 0 + } +} +impl Default for i32 { + fn default() -> i32 { + 0 + } +} +impl Default for i64 { + fn default() -> i64 { + 0 + } +} + +impl Default for () { + fn default() -> () { + () + } +} +impl Default for bool { + fn default() -> bool { + false + } +} + +impl Default for [T; N] +where + T: Default, +{ + fn default() -> [T; N] { + [T::default(); N] + } +} + +impl Default for [T] { + fn default() -> [T] { + &[] + } +} + +impl Default for (A, B) +where + A: Default, + B: Default, +{ + fn default() -> (A, B) { + (A::default(), B::default()) + } +} + +impl Default for (A, B, C) +where + A: Default, + B: Default, + C: Default, +{ + fn default() -> (A, B, C) { + (A::default(), B::default(), C::default()) + } +} + +impl Default for (A, B, C, D) +where + A: Default, + B: Default, + C: Default, + D: Default, +{ + fn default() -> (A, B, C, D) { + (A::default(), B::default(), C::default(), D::default()) + } +} + +impl Default for (A, B, C, D, E) +where + A: Default, + B: Default, + C: Default, + D: Default, + E: Default, +{ + fn default() -> (A, B, C, D, E) { + (A::default(), B::default(), C::default(), D::default(), E::default()) + } +} diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr new file mode 100644 index 00000000000..ec39e999715 --- /dev/null +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -0,0 +1,22 @@ +#[foreign(ecdsa_secp256k1)] +// docs:start:ecdsa_secp256k1 +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N], +) -> 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 new file mode 100644 index 00000000000..c7905b24f6f --- /dev/null +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -0,0 +1,21 @@ +#[foreign(ecdsa_secp256r1)] +// docs:start:ecdsa_secp256r1 +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N], +) -> 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/embedded_curve_ops.nr b/noir_stdlib/src/embedded_curve_ops.nr new file mode 100644 index 00000000000..6b225ee18b2 --- /dev/null +++ b/noir_stdlib/src/embedded_curve_ops.nr @@ -0,0 +1,207 @@ +use crate::cmp::Eq; +use crate::ops::arith::{Add, Neg, Sub}; + +/// A point on the embedded elliptic curve +/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field. +/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false. +pub struct EmbeddedCurvePoint { + pub x: Field, + pub y: Field, + pub is_infinite: bool, +} + +impl EmbeddedCurvePoint { + /// Elliptic curve point doubling operation + /// returns the doubled point of a point P, i.e P+P + pub fn double(self) -> EmbeddedCurvePoint { + embedded_curve_add(self, self) + } + + /// Returns the null element of the curve; 'the point at infinity' + pub fn point_at_infinity() -> EmbeddedCurvePoint { + EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true } + } +} + +impl Add for EmbeddedCurvePoint { + /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity + fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + embedded_curve_add(self, other) + } +} + +impl Sub for EmbeddedCurvePoint { + /// Points subtraction operation, using addition and negation + fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { + self + other.neg() + } +} + +impl Neg for EmbeddedCurvePoint { + /// Negates a point P, i.e returns -P, by negating the y coordinate. + /// If the point is at infinity, then the result is also at infinity. + fn neg(self) -> EmbeddedCurvePoint { + EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite } + } +} + +impl Eq for EmbeddedCurvePoint { + /// Checks whether two points are equal + 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 for the embedded curve represented as low and high limbs +/// By definition, the scalar field of the embedded curve is base field of the proving system curve. +/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs. +pub struct EmbeddedCurveScalar { + pub lo: Field, + pub hi: Field, +} + +impl EmbeddedCurveScalar { + pub fn new(lo: Field, hi: Field) -> Self { + EmbeddedCurveScalar { lo, hi } + } + + #[field(bn254)] + pub fn from_field(scalar: Field) -> EmbeddedCurveScalar { + let (a, b) = crate::field::bn254::decompose(scalar); + EmbeddedCurveScalar { lo: a, hi: b } + } + + //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value + #[field(bn254)] + pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> 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 = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi }; + sig_s + } +} + +impl Eq for EmbeddedCurveScalar { + fn eq(self, other: Self) -> bool { + (other.hi == self.hi) & (other.lo == self.lo) + } +} + +// 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. +// docs:start:multi_scalar_mul +pub fn multi_scalar_mul( + points: [EmbeddedCurvePoint; N], + scalars: [EmbeddedCurveScalar; N], +) -> EmbeddedCurvePoint +// docs:end:multi_scalar_mul +{ + let point_array = multi_scalar_mul_array_return(points, scalars); + EmbeddedCurvePoint { x: point_array[0], y: point_array[1], is_infinite: point_array[2] as bool } +} + +#[foreign(multi_scalar_mul)] +pub(crate) fn multi_scalar_mul_array_return( + points: [EmbeddedCurvePoint; N], + scalars: [EmbeddedCurveScalar; N], +) -> [Field; 3] {} + +// docs:start:fixed_base_scalar_mul +pub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint +// docs:end:fixed_base_scalar_mul +{ + let g1 = EmbeddedCurvePoint { + x: 1, + y: 17631683881184975370165255887551781615748388533673675138860, + is_infinite: false, + }; + multi_scalar_mul([g1], [scalar]) +} + +/// This function only assumes that the points are on the curve +/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe +// This is a hack because 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 +pub fn embedded_curve_add( + point1: EmbeddedCurvePoint, + point2: EmbeddedCurvePoint, +) -> EmbeddedCurvePoint { + // docs:end:embedded_curve_add + let x_coordinates_match = point1.x == point2.x; + let y_coordinates_match = point1.y == point2.y; + let double_predicate = (x_coordinates_match & y_coordinates_match); + let infinity_predicate = (x_coordinates_match & !y_coordinates_match); + let point1_1 = EmbeddedCurvePoint { + x: point1.x + (x_coordinates_match as Field), + y: point1.y, + is_infinite: x_coordinates_match, + }; + // point1_1 is guaranteed to have a different abscissa than point2 + let mut result = embedded_curve_add_unsafe(point1_1, point2); + result.is_infinite = x_coordinates_match; + + // dbl if x_match, y_match + let double = embedded_curve_add_unsafe(point1, point1); + result = if double_predicate { double } else { result }; + + // infinity if x_match, !y_match + if point1.is_infinite { + result = point2; + } + if point2.is_infinite { + result = point1; + } + let mut result_is_infinity = infinity_predicate & (!point1.is_infinite & !point2.is_infinite); + result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite); + result +} + +#[foreign(embedded_curve_add)] +fn embedded_curve_add_array_return( + _point1: EmbeddedCurvePoint, + _point2: EmbeddedCurvePoint, +) -> [Field; 3] {} + +/// This function assumes that: +/// The points are on the curve, and +/// The points don't share an x-coordinate, and +/// Neither point is the infinity point. +/// If it is used with correct input, the function ensures the correct non-zero result is returned. +/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected. +pub fn embedded_curve_add_not_nul( + point1: EmbeddedCurvePoint, + point2: EmbeddedCurvePoint, +) -> EmbeddedCurvePoint { + assert(point1.x != point2.x); + assert(!point1.is_infinite); + assert(!point2.is_infinite); + embedded_curve_add_unsafe(point1, point2) +} + +/// Unsafe ec addition +/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable. +/// If they have the same value but are different variables, the result will be incorrect because in this case +/// it assumes (but does not check) that the points' x-coordinates are not equal. +/// It also assumes neither point is the infinity point. +pub fn embedded_curve_add_unsafe( + 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, is_infinite: false } +} diff --git a/noir_stdlib/src/field/bn254.nr b/noir_stdlib/src/field/bn254.nr new file mode 100644 index 00000000000..a298a5d1e38 --- /dev/null +++ b/noir_stdlib/src/field/bn254.nr @@ -0,0 +1,213 @@ +use crate::field::field_less_than; +use crate::runtime::is_unconstrained; + +// The low and high decomposition of the field modulus +global PLO: Field = 53438638232309528389504892708671455233; +global PHI: Field = 64323764613183177041862057485226039389; + +pub(crate) global TWO_POW_128: Field = 0x100000000000000000000000000000000; +global TWO_POW_64: Field = 0x10000000000000000; + +// Decomposes a single field into two 16 byte fields. +fn compute_decomposition(mut x: Field) -> (Field, Field) { + // Here's we're taking advantage of truncating 64 bit limbs from the input field + // and then subtracting them from the input such the field division is equivalent to integer division. + let low_lower_64 = (x as u64) as Field; + x = (x - low_lower_64) / TWO_POW_64; + let low_upper_64 = (x as u64) as Field; + + let high = (x - low_upper_64) / TWO_POW_64; + let low = low_upper_64 * TWO_POW_64 + low_lower_64; + + (low, high) +} + +pub(crate) unconstrained fn decompose_hint(x: Field) -> (Field, Field) { + compute_decomposition(x) +} + +unconstrained fn lte_hint(x: Field, y: Field) -> bool { + if x == y { + true + } else { + field_less_than(x, y) + } +} + +// 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; + /// Safety: borrow is enforced to be boolean due to its type. + /// if borrow is 0, it asserts that (alo > blo && ahi >= bhi) + /// if borrow is 1, it asserts that (alo <= blo && ahi > bhi) + unsafe { + let borrow = lte_hint(alo, blo); + + 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>(); + } +} + +/// Decompose a single field into two 16 byte fields. +pub fn decompose(x: Field) -> (Field, Field) { + if is_unconstrained() { + compute_decomposition(x) + } else { + /// Safety: decomposition is properly checked below + 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( + /// Safety: already unconstrained + unsafe { field_less_than(b, a) }, + ); + } 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) { + assert_gt(b, a); +} + +pub fn gt(a: Field, b: Field) -> bool { + if is_unconstrained() { + /// Safety: unsafe in unconstrained + unsafe { + field_less_than(b, a) + } + } else if a == b { + false + } else { + /// Safety: Take a hint of the comparison and verify it + unsafe { + if field_less_than(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::{assert_gt, decompose, gt, lte_hint, PHI, PLO, TWO_POW_128}; + + #[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] + unconstrained fn check_lte_hint() { + assert(lte_hint(0, 1)); + assert(lte_hint(0, 0x100)); + assert(lte_hint(0x100, TWO_POW_128 - 1)); + assert(!lte_hint(0 - 1, 0)); + + assert(lte_hint(0, 0)); + assert(lte_hint(0x100, 0x100)); + assert(lte_hint(0 - 1, 0 - 1)); + } + + #[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/field/mod.nr b/noir_stdlib/src/field/mod.nr new file mode 100644 index 00000000000..d0760447ff1 --- /dev/null +++ b/noir_stdlib/src/field/mod.nr @@ -0,0 +1,332 @@ +pub mod bn254; +use crate::runtime::is_unconstrained; +use bn254::lt as bn254_lt; + +impl Field { + /// Asserts that `self` can be represented in `bit_size` bits. + /// + /// # Failures + /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`. + // docs:start:assert_max_bit_size + pub fn assert_max_bit_size(self) { + // docs:end:assert_max_bit_size + assert(BIT_SIZE < modulus_num_bits() as u32); + self.__assert_max_bit_size(BIT_SIZE); + } + + #[builtin(apply_range_constraint)] + fn __assert_max_bit_size(self, bit_size: u32) {} + + /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array. + /// This slice will be zero padded should not all bits be necessary to represent `self`. + /// + /// # Failures + /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not + /// be able to represent the original `Field`. + /// + /// # Safety + /// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus + /// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will + /// wrap around due to overflow when verifying the decomposition. + #[builtin(to_le_bits)] + // docs:start:to_le_bits + pub fn to_le_bits(self: Self) -> [u1; N] {} + // docs:end:to_le_bits + + /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array. + /// This array will be zero padded should not all bits be necessary to represent `self`. + /// + /// # Failures + /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not + /// be able to represent the original `Field`. + /// + /// # Safety + /// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus + /// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will + /// wrap around due to overflow when verifying the decomposition. + #[builtin(to_be_bits)] + // docs:start:to_be_bits + pub fn to_be_bits(self: Self) -> [u1; N] {} + // docs:end:to_be_bits + + /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array + /// This array will be zero padded should not all bytes be necessary to represent `self`. + /// + /// # Failures + /// The length N of the array must be big enough to contain all the bytes of the 'self', + /// and no more than the number of bytes required to represent the field modulus + /// + /// # Safety + /// The result is ensured to be the canonical decomposition of the field element + // docs:start:to_le_bytes + pub fn to_le_bytes(self: Self) -> [u8; N] { + // docs:end:to_le_bytes + // Compute the byte decomposition + let bytes = self.to_le_radix(256); + + if !is_unconstrained() { + // Ensure that the byte decomposition does not overflow the modulus + let p = modulus_le_bytes(); + assert(bytes.len() <= p.len()); + let mut ok = bytes.len() != p.len(); + for i in 0..N { + if !ok { + if (bytes[N - 1 - i] != p[N - 1 - i]) { + assert(bytes[N - 1 - i] < p[N - 1 - i]); + ok = true; + } + } + } + assert(ok); + } + bytes + } + + /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus + /// This array will be zero padded should not all bytes be necessary to represent `self`. + /// + /// # Failures + /// The length N of the array must be big enough to contain all the bytes of the 'self', + /// and no more than the number of bytes required to represent the field modulus + /// + /// # Safety + /// The result is ensured to be the canonical decomposition of the field element + // docs:start:to_be_bytes + pub fn to_be_bytes(self: Self) -> [u8; N] { + // docs:end:to_be_bytes + // Compute the byte decomposition + let bytes = self.to_be_radix(256); + + if !is_unconstrained() { + // Ensure that the byte decomposition does not overflow the modulus + let p = modulus_be_bytes(); + assert(bytes.len() <= p.len()); + let mut ok = bytes.len() != p.len(); + for i in 0..N { + if !ok { + if (bytes[i] != p[i]) { + assert(bytes[i] < p[i]); + ok = true; + } + } + } + assert(ok); + } + bytes + } + + // docs:start:to_le_radix + pub fn to_le_radix(self: Self, radix: u32) -> [u8; N] { + // Brillig does not need an immediate radix + if !crate::runtime::is_unconstrained() { + crate::assert_constant(radix); + } + self.__to_le_radix(radix) + } + // docs:end:to_le_radix + + // docs:start:to_be_radix + pub fn to_be_radix(self: Self, radix: u32) -> [u8; N] { + // Brillig does not need an immediate radix + if !crate::runtime::is_unconstrained() { + crate::assert_constant(radix); + } + self.__to_be_radix(radix) + } + // docs:end:to_be_radix + + // `_radix` must be less than 256 + #[builtin(to_le_radix)] + fn __to_le_radix(self, radix: u32) -> [u8; N] {} + + #[builtin(to_be_radix)] + fn __to_be_radix(self, radix: u32) -> [u8; N] {} + + // Returns self to the power of the given exponent value. + // Caution: we assume the exponent fits into 32 bits + // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits + pub fn pow_32(self, exponent: Field) -> Field { + let mut r: Field = 1; + let b: [u1; 32] = exponent.to_le_bits(); + + for i in 1..33 { + r *= r; + r = (b[32 - i] as Field) * (r * self) + (1 - b[32 - i] as Field) * r; + } + r + } + + // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. + pub fn sgn0(self) -> u1 { + self as u1 + } + + pub fn lt(self, another: Field) -> bool { + if crate::compat::is_bn254() { + bn254_lt(self, another) + } else { + lt_fallback(self, another) + } + } + + /// Convert a little endian byte array to a field element. + /// If the provided byte array overflows the field modulus then the Field will silently wrap around. + pub fn from_le_bytes(bytes: [u8; N]) -> Field { + let mut v = 1; + let mut result = 0; + + for i in 0..N { + result += (bytes[i] as Field) * v; + v = v * 256; + } + result + } + + /// Convert a big endian byte array to a field element. + /// If the provided byte array overflows the field modulus then the Field will silently wrap around. + pub fn from_be_bytes(bytes: [u8; N]) -> Field { + let mut v = 1; + let mut result = 0; + + for i in 0..N { + result += (bytes[N - 1 - i] as Field) * v; + v = v * 256; + } + result + } +} + +#[builtin(modulus_num_bits)] +pub comptime fn modulus_num_bits() -> u64 {} + +#[builtin(modulus_be_bits)] +pub comptime fn modulus_be_bits() -> [u1] {} + +#[builtin(modulus_le_bits)] +pub comptime fn modulus_le_bits() -> [u1] {} + +#[builtin(modulus_be_bytes)] +pub comptime fn modulus_be_bytes() -> [u8] {} + +#[builtin(modulus_le_bytes)] +pub comptime fn modulus_le_bytes() -> [u8] {} + +/// An unconstrained only built in to efficiently compare fields. +#[builtin(field_less_than)] +unconstrained fn __field_less_than(x: Field, y: Field) -> bool {} + +pub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool { + __field_less_than(x, y) +} + +// 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; + let mut high = 0 as Field; + let mut low = 0 as Field; + + for i in 0..16 { + high = high + (bytes32[15 - i] as Field) * v; + low = low + (bytes32[16 + 15 - i] as Field) * v; + v = v * 256; + } + // Abuse that a % p + b % p = (a + b) % p and that low < p + low + high * v +} + +fn lt_fallback(x: Field, y: Field) -> bool { + if is_unconstrained() { + /// Safety: unconstrained context + unsafe { + field_less_than(x, y) + } + } else { + let x_bytes: [u8; 32] = x.to_le_bytes(); + let y_bytes: [u8; 32] = y.to_le_bytes(); + let mut x_is_lt = false; + let mut done = false; + for i in 0..32 { + if (!done) { + let x_byte = x_bytes[32 - 1 - i] as u8; + let y_byte = y_bytes[32 - 1 - i] as u8; + let bytes_match = x_byte == y_byte; + if !bytes_match { + x_is_lt = x_byte < y_byte; + done = true; + } + } + } + x_is_lt + } +} + +mod tests { + use super::field_less_than; + + #[test] + // docs:start:to_be_bits_example + fn test_to_be_bits() { + let field = 2; + let bits: [u1; 8] = field.to_be_bits(); + assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]); + } + // docs:end:to_be_bits_example + + #[test] + // docs:start:to_le_bits_example + fn test_to_le_bits() { + let field = 2; + let bits: [u1; 8] = field.to_le_bits(); + assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]); + } + // docs:end:to_le_bits_example + + #[test] + // docs:start:to_be_bytes_example + fn test_to_be_bytes() { + let field = 2; + let bytes: [u8; 8] = field.to_be_bytes(); + assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]); + assert_eq(Field::from_be_bytes::<8>(bytes), field); + } + // docs:end:to_be_bytes_example + + #[test] + // docs:start:to_le_bytes_example + fn test_to_le_bytes() { + let field = 2; + let bytes: [u8; 8] = field.to_le_bytes(); + assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]); + assert_eq(Field::from_le_bytes::<8>(bytes), field); + } + // docs:end:to_le_bytes_example + + #[test] + // docs:start:to_be_radix_example + fn test_to_be_radix() { + let field = 2; + let bytes: [u8; 8] = field.to_be_radix(256); + assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]); + assert_eq(Field::from_be_bytes::<8>(bytes), field); + } + // docs:end:to_be_radix_example + + #[test] + // docs:start:to_le_radix_example + fn test_to_le_radix() { + let field = 2; + let bytes: [u8; 8] = field.to_le_radix(256); + assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]); + assert_eq(Field::from_le_bytes::<8>(bytes), field); + } + // docs:end:to_le_radix_example + + #[test] + unconstrained fn test_field_less_than() { + assert(field_less_than(0, 1)); + assert(field_less_than(0, 0x100)); + assert(field_less_than(0x100, 0 - 1)); + assert(!field_less_than(0 - 1, 0)); + } +} diff --git a/noir_stdlib/src/hash/keccak.nr b/noir_stdlib/src/hash/keccak.nr new file mode 100644 index 00000000000..93b366d1ec1 --- /dev/null +++ b/noir_stdlib/src/hash/keccak.nr @@ -0,0 +1,154 @@ +use crate::runtime::is_unconstrained; + +global BLOCK_SIZE_IN_BYTES: u32 = 136; //(1600 - BITS * 2) / WORD_SIZE; +global WORD_SIZE: u32 = 8; // Limbs are made up of u64s so 8 bytes each. +global LIMBS_PER_BLOCK: u32 = BLOCK_SIZE_IN_BYTES / WORD_SIZE; +global NUM_KECCAK_LANES: u32 = 25; + +#[foreign(keccakf1600)] +fn keccakf1600(input: [u64; 25]) -> [u64; 25] {} + +#[no_predicates] +pub(crate) fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] { + assert(N >= message_size); + + // Copy input to block bytes. For that we'll need at least input bytes (N) + // but we want it to be padded to a multiple of BLOCK_SIZE_IN_BYTES. + let mut block_bytes = [0; ((N / BLOCK_SIZE_IN_BYTES) + 1) * BLOCK_SIZE_IN_BYTES]; + if is_unconstrained() { + for i in 0..message_size { + block_bytes[i] = input[i]; + } + } else { + for i in 0..N { + if i < message_size { + block_bytes[i] = input[i]; + } + } + } + + //1. format_input_lanes + let max_blocks = (N + BLOCK_SIZE_IN_BYTES) / BLOCK_SIZE_IN_BYTES; + //maximum number of bytes to hash + let real_max_blocks = (message_size + BLOCK_SIZE_IN_BYTES) / BLOCK_SIZE_IN_BYTES; + let real_blocks_bytes = real_max_blocks * BLOCK_SIZE_IN_BYTES; + + block_bytes[message_size] = 1; + block_bytes[real_blocks_bytes - 1] = 0x80; + + // populate a vector of 64-bit limbs from our byte array + let mut sliced_buffer = + [0; (((N / BLOCK_SIZE_IN_BYTES) + 1) * BLOCK_SIZE_IN_BYTES) / WORD_SIZE]; + for i in 0..sliced_buffer.len() { + let limb_start = WORD_SIZE * i; + + let mut sliced = 0; + let mut v = 1; + for k in 0..WORD_SIZE { + sliced += v * (block_bytes[limb_start + k] as Field); + v *= 256; + } + + sliced_buffer[i] = sliced as u64; + } + + //2. sponge_absorb + let mut state: [u64; NUM_KECCAK_LANES] = [0; NUM_KECCAK_LANES]; + // When in an unconstrained runtime we can take advantage of runtime loop bounds, + // thus allowing us to simplify the loop body. + if is_unconstrained() { + for i in 0..real_max_blocks { + if (i == 0) { + for j in 0..LIMBS_PER_BLOCK { + state[j] = sliced_buffer[j]; + } + } else { + for j in 0..LIMBS_PER_BLOCK { + state[j] = state[j] ^ sliced_buffer[i * LIMBS_PER_BLOCK + j]; + } + } + state = keccakf1600(state); + } + } else { + // `real_max_blocks` is guaranteed to at least be `1` + // We peel out the first block as to avoid a conditional inside of the loop. + // Otherwise, a dynamic predicate can cause a blowup in a constrained runtime. + for j in 0..LIMBS_PER_BLOCK { + state[j] = sliced_buffer[j]; + } + state = keccakf1600(state); + for i in 1..max_blocks { + if i < real_max_blocks { + for j in 0..LIMBS_PER_BLOCK { + state[j] = state[j] ^ sliced_buffer[i * LIMBS_PER_BLOCK + j]; + } + state = keccakf1600(state); + } + } + } + + //3. sponge_squeeze + let mut result = [0; 32]; + for i in 0..4 { + let lane = state[i] as Field; + let lane_le: [u8; 8] = lane.to_le_bytes(); + for j in 0..8 { + result[8 * i + j] = lane_le[j]; + } + } + result +} + +mod tests { + use super::keccak256; + + #[test] + fn smoke_test() { + let input = [0xbd]; + let result = [ + 0x5a, 0x50, 0x2f, 0x9f, 0xca, 0x46, 0x7b, 0x26, 0x6d, 0x5b, 0x78, 0x33, 0x65, 0x19, + 0x37, 0xe8, 0x05, 0x27, 0x0c, 0xa3, 0xf3, 0xaf, 0x1c, 0x0d, 0xd2, 0x46, 0x2d, 0xca, + 0x4b, 0x3b, 0x1a, 0xbf, + ]; + assert_eq(keccak256(input, input.len()), result); + } + + #[test] + fn hash_hello_world() { + let input = "Hello world!".as_bytes(); + let result = [ + 0xec, 0xd0, 0xe1, 0x8, 0xa9, 0x8e, 0x19, 0x2a, 0xf1, 0xd2, 0xc2, 0x50, 0x55, 0xf4, 0xe3, + 0xbe, 0xd7, 0x84, 0xb5, 0xc8, 0x77, 0x20, 0x4e, 0x73, 0x21, 0x9a, 0x52, 0x3, 0x25, 0x1f, + 0xea, 0xab, + ]; + assert_eq(keccak256(input, input.len()), result); + } + + #[test] + fn var_size_hash() { + let input = [ + 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, + ]; + let result = [ + 226, 37, 115, 94, 94, 196, 72, 116, 194, 105, 79, 233, 65, 12, 30, 94, 181, 131, 170, + 219, 171, 166, 236, 88, 143, 67, 255, 160, 248, 214, 39, 129, + ]; + assert_eq(keccak256(input, 13), result); + } + + #[test] + fn hash_longer_than_136_bytes() { + let input = "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789" + .as_bytes(); + assert(input.len() > 136); + + let result = [ + 0x1d, 0xca, 0xeb, 0xdf, 0xd9, 0xd6, 0x24, 0x67, 0x1c, 0x18, 0x16, 0xda, 0xd, 0x8a, 0xeb, + 0xa8, 0x75, 0x71, 0x2c, 0xc, 0x89, 0xe0, 0x25, 0x2, 0xe8, 0xb6, 0x5e, 0x16, 0x5, 0x55, + 0xe4, 0x40, + ]; + assert_eq(keccak256(input, input.len()), result); + } +} diff --git a/noir_stdlib/src/hash/mod.nr b/noir_stdlib/src/hash/mod.nr new file mode 100644 index 00000000000..104368b50fa --- /dev/null +++ b/noir_stdlib/src/hash/mod.nr @@ -0,0 +1,529 @@ +pub mod poseidon; +pub mod poseidon2; +pub mod keccak; +pub mod sha256; +pub mod sha512; + +use crate::default::Default; +use crate::embedded_curve_ops::{ + EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return, +}; +use crate::meta::derive_via; +use crate::uint128::U128; + +// Kept for backwards compatibility +pub use sha256::{digest, sha256, sha256_compression, sha256_var}; + +#[foreign(blake2s)] +// docs:start:blake2s +pub fn blake2s(input: [u8; N]) -> [u8; 32] +// docs:end:blake2s +{} + +#[foreign(blake3)] +// docs:start:blake3 +pub fn blake3(input: [u8; N]) -> [u8; 32] +// docs:end:blake3 +{} + +// docs:start:pedersen_commitment +pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { + // docs:end:pedersen_commitment + pedersen_commitment_with_separator(input, 0) +} + +#[inline_always] +pub fn pedersen_commitment_with_separator( + input: [Field; N], + separator: u32, +) -> EmbeddedCurvePoint { + let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N]; + for i in 0..N { + // we use the unsafe version because the multi_scalar_mul will constrain the scalars. + points[i] = from_field_unsafe(input[i]); + } + let generators = derive_generators("DEFAULT_DOMAIN_SEPARATOR".as_bytes(), separator); + multi_scalar_mul(generators, points) +} + +// docs:start:pedersen_hash +pub fn pedersen_hash(input: [Field; N]) -> Field +// docs:end:pedersen_hash +{ + pedersen_hash_with_separator(input, 0) +} + +#[no_predicates] +pub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field { + let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1]; + let mut generators: [EmbeddedCurvePoint; N + 1] = + [EmbeddedCurvePoint::point_at_infinity(); N + 1]; + let domain_generators: [EmbeddedCurvePoint; N] = + derive_generators("DEFAULT_DOMAIN_SEPARATOR".as_bytes(), separator); + + for i in 0..N { + scalars[i] = from_field_unsafe(input[i]); + generators[i] = domain_generators[i]; + } + scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field }; + + let length_generator: [EmbeddedCurvePoint; 1] = + derive_generators("pedersen_hash_length".as_bytes(), 0); + generators[N] = length_generator[0]; + multi_scalar_mul_array_return(generators, scalars)[0] +} + +#[field(bn254)] +#[inline_always] +pub fn derive_generators( + domain_separator_bytes: [u8; M], + starting_index: u32, +) -> [EmbeddedCurvePoint; N] { + crate::assert_constant(domain_separator_bytes); + // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index + __derive_generators(domain_separator_bytes, starting_index) +} + +#[builtin(derive_pedersen_generators)] +#[field(bn254)] +fn __derive_generators( + domain_separator_bytes: [u8; M], + starting_index: u32, +) -> [EmbeddedCurvePoint; N] {} + +#[field(bn254)] +// Same as from_field but: +// does not assert the limbs are 128 bits +// does not assert the decomposition does not overflow the EmbeddedCurveScalar +fn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar { + /// Safety: xlo and xhi decomposition is checked below + let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) }; + // Check that the decomposition is correct + assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi); + EmbeddedCurveScalar { lo: xlo, hi: xhi } +} + +pub fn hash_to_field(inputs: [Field]) -> Field { + let mut sum = 0; + + for input in inputs { + let input_bytes: [u8; 32] = input.to_le_bytes(); + sum += crate::field::bytes32_to_field(blake2s(input_bytes)); + } + + sum +} + +// docs:start:keccak256 +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +// docs:end:keccak256 +{ + crate::hash::keccak::keccak256(input, message_size) +} + +#[foreign(poseidon2_permutation)] +pub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {} + +// Generic hashing support. +// Partially ported and impacted by rust. + +// Hash trait shall be implemented per type. +#[derive_via(derive_hash)] +pub trait Hash { + fn hash(self, state: &mut H) + where + H: Hasher; +} + +// docs:start:derive_hash +comptime fn derive_hash(s: StructDefinition) -> Quoted { + let name = quote { Hash }; + let signature = quote { fn hash(_self: Self, _state: &mut H) where H: std::hash::Hasher }; + let for_each_field = |name| quote { _self.$name.hash(_state); }; + crate::meta::make_trait_impl( + s, + name, + signature, + for_each_field, + quote {}, + |fields| fields, + ) +} +// docs:end:derive_hash + +// Hasher trait shall be implemented by algorithms to provide hash-agnostic means. +// TODO: consider making the types generic here ([u8], [Field], etc.) +pub trait Hasher { + fn finish(self) -> Field; + + fn write(&mut self, input: Field); +} + +// BuildHasher is a factory trait, responsible for production of specific Hasher. +pub trait BuildHasher +where + H: Hasher, +{ + fn build_hasher(self) -> H; +} + +pub struct BuildHasherDefault; + +impl BuildHasher for BuildHasherDefault +where + H: Hasher + Default, +{ + fn build_hasher(_self: Self) -> H { + H::default() + } +} + +impl Default for BuildHasherDefault +where + H: Hasher + Default, +{ + fn default() -> Self { + BuildHasherDefault {} + } +} + +impl Hash for Field { + fn hash(self, state: &mut H) + where + H: Hasher, + { + H::write(state, self); + } +} + +impl Hash for u1 { + fn hash(self, state: &mut H) + where + H: Hasher, + { + H::write(state, self as Field); + } +} + +impl Hash for u8 { + fn hash(self, state: &mut H) + where + H: Hasher, + { + H::write(state, self as Field); + } +} + +impl Hash for u16 { + 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 i16 { + 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, + { + self.0.hash(state); + self.1.hash(state); + self.2.hash(state); + self.3.hash(state); + self.4.hash(state); + } +} + +// Some test vectors for Pedersen hash and Pedersen Commitment. +// They have been generated using the same functions so the tests are for now useless +// but they will be useful when we switch to Noir implementation. +#[test] +fn assert_pedersen() { + assert_eq( + pedersen_hash_with_separator([1], 1), + 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f, + ); + assert_eq( + pedersen_commitment_with_separator([1], 1), + EmbeddedCurvePoint { + x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402, + y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126, + is_infinite: false, + }, + ); + + assert_eq( + pedersen_hash_with_separator([1, 2], 2), + 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255, + ); + assert_eq( + pedersen_commitment_with_separator([1, 2], 2), + EmbeddedCurvePoint { + x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753, + y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778, + is_infinite: false, + }, + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3], 3), + 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4, + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3], 3), + EmbeddedCurvePoint { + x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85, + y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1, + is_infinite: false, + }, + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4], 4), + 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc, + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4], 4), + EmbeddedCurvePoint { + x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9, + y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014, + is_infinite: false, + }, + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5], 5), + 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22, + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5), + EmbeddedCurvePoint { + x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29, + y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7, + is_infinite: false, + }, + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6), + 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572, + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6), + EmbeddedCurvePoint { + x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697, + y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb, + is_infinite: false, + }, + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7), + 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3, + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7), + EmbeddedCurvePoint { + x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939, + y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc, + is_infinite: false, + }, + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8), + 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c, + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8), + EmbeddedCurvePoint { + x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443, + y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77, + is_infinite: false, + }, + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9), + 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7, + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9), + EmbeddedCurvePoint { + x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d, + y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2, + is_infinite: false, + }, + ); + assert_eq( + pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10), + 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94, + ); + assert_eq( + pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10), + EmbeddedCurvePoint { + x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c, + y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245, + is_infinite: false, + }, + ); +} diff --git a/noir_stdlib/src/hash/poseidon/bn254.nr b/noir_stdlib/src/hash/poseidon/bn254.nr new file mode 100644 index 00000000000..23591fb69c8 --- /dev/null +++ b/noir_stdlib/src/hash/poseidon/bn254.nr @@ -0,0 +1,173 @@ +// Instantiations of Poseidon constants, permutations and sponge for prime field of the same order as BN254 +pub mod perm; +pub mod consts; + +use crate::hash::poseidon::absorb; + +// Variable-length Poseidon-128 sponge as suggested in second bullet point of section 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 +#[no_predicates] +pub fn hash_1(input: [Field; 1]) -> Field { + let mut state = [0; 2]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_2(state)[0] +} + +#[no_predicates] +pub fn hash_2(input: [Field; 2]) -> Field { + let mut state = [0; 3]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_3(state)[0] +} + +#[no_predicates] +pub fn hash_3(input: [Field; 3]) -> Field { + let mut state = [0; 4]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_4(state)[0] +} + +#[no_predicates] +pub fn hash_4(input: [Field; 4]) -> Field { + let mut state = [0; 5]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_5(state)[0] +} + +#[no_predicates] +pub fn hash_5(input: [Field; 5]) -> Field { + let mut state = [0; 6]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_6(state)[0] +} + +#[no_predicates] +pub fn hash_6(input: [Field; 6]) -> Field { + let mut state = [0; 7]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_7(state)[0] +} + +#[no_predicates] +pub fn hash_7(input: [Field; 7]) -> Field { + let mut state = [0; 8]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_8(state)[0] +} + +#[no_predicates] +pub fn hash_8(input: [Field; 8]) -> Field { + let mut state = [0; 9]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_9(state)[0] +} + +#[no_predicates] +pub fn hash_9(input: [Field; 9]) -> Field { + let mut state = [0; 10]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_10(state)[0] +} + +#[no_predicates] +pub fn hash_10(input: [Field; 10]) -> Field { + let mut state = [0; 11]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_11(state)[0] +} + +#[no_predicates] +pub fn hash_11(input: [Field; 11]) -> Field { + let mut state = [0; 12]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_12(state)[0] +} + +#[no_predicates] +pub fn hash_12(input: [Field; 12]) -> Field { + let mut state = [0; 13]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_13(state)[0] +} + +#[no_predicates] +pub fn hash_13(input: [Field; 13]) -> Field { + let mut state = [0; 14]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_14(state)[0] +} + +#[no_predicates] +pub fn hash_14(input: [Field; 14]) -> Field { + let mut state = [0; 15]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_15(state)[0] +} + +#[no_predicates] +pub fn hash_15(input: [Field; 15]) -> Field { + let mut state = [0; 16]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_16(state)[0] +} + +#[no_predicates] +pub fn hash_16(input: [Field; 16]) -> Field { + let mut state = [0; 17]; + for i in 0..input.len() { + state[i + 1] = input[i]; + } + + perm::x5_17(state)[0] +} diff --git a/noir_stdlib/src/hash/poseidon/bn254/consts.nr b/noir_stdlib/src/hash/poseidon/bn254/consts.nr new file mode 100644 index 00000000000..42df0ef662f --- /dev/null +++ b/noir_stdlib/src/hash/poseidon/bn254/consts.nr @@ -0,0 +1,24965 @@ +// 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::config; +use crate::hash::poseidon::PoseidonConfig; +// S-box power +fn alpha() -> Field { + 5 +} + +// noir-fmt:ignore +pub fn x5_2_config() -> PoseidonConfig<2, 72, 168> { + config( + 2, + 8, + 56, + alpha(), + [ + 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<3, 81, 285> { + config( + 3, + 8, + 57, + 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<4, 88, 392> { + config( + 4, + 8, + 56, + alpha(), + [ + 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<5, 100, 540> { + config( + 5, + 8, + 60, + alpha(), + [ + 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<6, 108, 660> { + config( + 6, + 8, + 60, + alpha(), + [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<7, 119, 819> { + config( + 7, + 8, + 63, + alpha(), + [ + 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<8, 128, 960> { + config( + 8, + 8, + 64, + alpha(), + [ + 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<9, 135, 1071> { + config( + 9, + 8, + 63, + alpha(), + [ + 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<10, 140, 1140> { + config( + 10, + 8, + 60, + alpha(), + [ + 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<11, 154, 1386> { + config( + 11, + 8, + 66, + alpha(), + [ + 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<12, 156, 1380> { + config( + 12, + 8, + 60, + alpha(), + [ + 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<13, 169, 1625> { + config( + 13, + 8, + 65, + alpha(), + [ + 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<14, 182, 1890> { + config( + 14, + 8, + 70, + alpha(), + [ + 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<15, 180, 1740> { + config( + 15, + 8, + 60, + alpha(), + [ + 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<16, 192, 1984> { + config( + 16, + 8, + 64, + alpha(), + [ + 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<17, 204, 2244> { + config( + 17, + 8, + 68, + alpha(), + [ + 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 new file mode 100644 index 00000000000..3a12f59fe77 --- /dev/null +++ b/noir_stdlib/src/hash/poseidon/bn254/perm.nr @@ -0,0 +1,115 @@ +// Instantiations of Poseidon permutation for the prime field of the same order as BN254 +use crate::hash::poseidon::bn254::consts; +use crate::hash::poseidon::permute; + +#[field(bn254)] +pub fn x5_2(mut state: [Field; 2]) -> [Field; 2] { + state = permute(consts::x5_2_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_3(mut state: [Field; 3]) -> [Field; 3] { + state = permute(consts::x5_3_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_4(mut state: [Field; 4]) -> [Field; 4] { + state = permute(consts::x5_4_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_5(mut state: [Field; 5]) -> [Field; 5] { + state = permute(consts::x5_5_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_6(mut state: [Field; 6]) -> [Field; 6] { + state = permute(consts::x5_6_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_7(mut state: [Field; 7]) -> [Field; 7] { + state = permute(consts::x5_7_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_8(mut state: [Field; 8]) -> [Field; 8] { + state = permute(consts::x5_8_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_9(mut state: [Field; 9]) -> [Field; 9] { + state = permute(consts::x5_9_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_10(mut state: [Field; 10]) -> [Field; 10] { + state = permute(consts::x5_10_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_11(mut state: [Field; 11]) -> [Field; 11] { + state = permute(consts::x5_11_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_12(mut state: [Field; 12]) -> [Field; 12] { + state = permute(consts::x5_12_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_13(mut state: [Field; 13]) -> [Field; 13] { + state = permute(consts::x5_13_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_14(mut state: [Field; 14]) -> [Field; 14] { + state = permute(consts::x5_14_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_15(mut state: [Field; 15]) -> [Field; 15] { + state = permute(consts::x5_15_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_16(mut state: [Field; 16]) -> [Field; 16] { + state = permute(consts::x5_16_config(), state); + + state +} + +#[field(bn254)] +pub fn x5_17(mut state: [Field; 17]) -> [Field; 17] { + state = permute(consts::x5_17_config(), state); + + state +} diff --git a/noir_stdlib/src/hash/poseidon/mod.nr b/noir_stdlib/src/hash/poseidon/mod.nr new file mode 100644 index 00000000000..e2e47959024 --- /dev/null +++ b/noir_stdlib/src/hash/poseidon/mod.nr @@ -0,0 +1,396 @@ +pub mod bn254; // Instantiations of Poseidon for prime field of the same order as BN254 +use crate::default::Default; +use crate::hash::Hasher; + +// 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/ +pub 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( + t: Field, + rf: u8, + rp: u8, + alpha: Field, + round_constants: [Field; N], + mds: [[Field; T]; T], + presparse_mds: [[Field; T]; T], + sparse_mds: [Field; X], +) -> PoseidonConfig { + // Input checks + assert_eq(rf & 1, 0); + assert_eq((t as u8) * rf + rp, N as u8); + assert_eq(t, T as Field); + assert(alpha != 0); + + PoseidonConfig { t, rf, rp, alpha, round_constants, mds, presparse_mds, sparse_mds } +} + +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; + + 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); + 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]); + } + } + } + } + + 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 +} + +// 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; + + 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 +} + +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 +} + +pub 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 + } + + #[inline_always] + 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/poseidon2.nr b/noir_stdlib/src/hash/poseidon2.nr new file mode 100644 index 00000000000..419f07a2aca --- /dev/null +++ b/noir_stdlib/src/hash/poseidon2.nr @@ -0,0 +1,109 @@ +use crate::default::Default; +use crate::hash::Hasher; + +comptime global RATE: u32 = 3; + +pub struct Poseidon2 { + cache: [Field; 3], + state: [Field; 4], + cache_size: u32, + squeeze_mode: bool, // 0 => absorb, 1 => squeeze +} + +impl Poseidon2 { + #[no_predicates] + pub fn hash(input: [Field; N], message_size: u32) -> Field { + Poseidon2::hash_internal(input, message_size, message_size != N) + } + + pub(crate) fn new(iv: Field) -> Poseidon2 { + let mut result = + Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false }; + result.state[RATE] = iv; + result + } + + fn perform_duplex(&mut self) { + // add the cache into sponge state + for i in 0..RATE { + // We effectively zero-pad the cache by only adding to the state + // cache that is less than the specified `cache_size` + if i < self.cache_size { + self.state[i] += self.cache[i]; + } + } + self.state = crate::hash::poseidon2_permutation(self.state, 4); + } + + fn absorb(&mut self, input: Field) { + assert(!self.squeeze_mode); + if self.cache_size == RATE { + // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache + self.perform_duplex(); + self.cache[0] = input; + self.cache_size = 1; + } else { + // If we're absorbing, and the cache is not full, add the input into the cache + self.cache[self.cache_size] = input; + self.cache_size += 1; + } + } + + fn squeeze(&mut self) -> Field { + assert(!self.squeeze_mode); + // If we're in absorb mode, apply sponge permutation to compress the cache. + self.perform_duplex(); + self.squeeze_mode = true; + + // Pop one item off the top of the permutation and return it. + self.state[0] + } + + fn hash_internal( + input: [Field; N], + in_len: u32, + is_variable_length: bool, + ) -> Field { + let two_pow_64 = 18446744073709551616; + let iv: Field = (in_len as Field) * two_pow_64; + let mut sponge = Poseidon2::new(iv); + for i in 0..input.len() { + if i < in_len { + sponge.absorb(input[i]); + } + } + + // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish + // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures + // fixed-length and variable-length hashes do not collide) + if is_variable_length { + sponge.absorb(1); + } + sponge.squeeze() + } +} + +pub 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/hash/sha256.nr b/noir_stdlib/src/hash/sha256.nr new file mode 100644 index 00000000000..fce263ce25d --- /dev/null +++ b/noir_stdlib/src/hash/sha256.nr @@ -0,0 +1,843 @@ +use crate::runtime::is_unconstrained; + +// Implementation of SHA-256 mapping a byte array of variable length to +// 32 bytes. + +// A message block is up to 64 bytes taken from the input. +global BLOCK_SIZE: u32 = 64; + +// The first index in the block where the 8 byte message size will be written. +global MSG_SIZE_PTR: u32 = 56; + +// Size of the message block when packed as 4-byte integer array. +global INT_BLOCK_SIZE: u32 = 16; + +// A `u32` integer consists of 4 bytes. +global INT_SIZE: u32 = 4; + +// Index of the integer in the `INT_BLOCK` where the length is written. +global INT_SIZE_PTR: u32 = MSG_SIZE_PTR / INT_SIZE; + +// Magic numbers for bit shifting. +// Works with actual bit shifting as well as the compiler turns them into * and / +// but circuit execution appears to be 10% faster this way. +global TWO_POW_8: u32 = 256; +global TWO_POW_16: u32 = TWO_POW_8 * 256; +global TWO_POW_24: u32 = TWO_POW_16 * 256; +global TWO_POW_32: u64 = TWO_POW_24 as u64 * 256; + +// Index of a byte in a 64 byte block; ie. 0..=63 +type BLOCK_BYTE_PTR = u32; + +// The foreign function to compress blocks works on 16 pieces of 4-byte integers, instead of 64 bytes. +type INT_BLOCK = [u32; INT_BLOCK_SIZE]; + +// A message block is a slice of the original message of a fixed size, +// potentially padded with zeros, with neighbouring 4 bytes packed into integers. +type MSG_BLOCK = INT_BLOCK; + +// The hash is 32 bytes. +type HASH = [u8; 32]; + +// The state accumulates the blocks. +// Its overall size is the same as the `HASH`. +type STATE = [u32; 8]; + +// Deprecated in favour of `sha256_var` +// docs:start:sha256 +pub fn sha256(input: [u8; N]) -> HASH +// docs:end:sha256 +{ + digest(input) +} + +#[foreign(sha256_compression)] +pub fn sha256_compression(_input: INT_BLOCK, _state: STATE) -> STATE {} + +// SHA-256 hash function +#[no_predicates] +pub fn digest(msg: [u8; N]) -> HASH { + sha256_var(msg, N as u64) +} + +// Variable size SHA-256 hash +pub fn sha256_var(msg: [u8; N], message_size: u64) -> HASH { + let message_size = message_size as u32; + let num_blocks = N / BLOCK_SIZE; + let mut msg_block: MSG_BLOCK = [0; INT_BLOCK_SIZE]; + // Intermediate hash, starting with the canonical initial value + let mut h: STATE = [ + 1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, + 1541459225, + ]; + // Pointer into msg_block on a 64 byte scale + let mut msg_byte_ptr = 0; + for i in 0..num_blocks { + let msg_start = BLOCK_SIZE * i; + /// Safety: the msg_block is checked below in verify_msg_block + let (new_msg_block, new_msg_byte_ptr) = + unsafe { build_msg_block(msg, message_size, msg_start) }; + + if msg_start < message_size { + msg_block = new_msg_block; + } + + if !is_unconstrained() { + // Verify the block we are compressing was appropriately constructed + let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); + if msg_start < message_size { + msg_byte_ptr = new_msg_byte_ptr; + } + } else if msg_start < message_size { + msg_byte_ptr = new_msg_byte_ptr; + } + + // If the block is filled, compress it. + // An un-filled block is handled after this loop. + if (msg_start < message_size) & (msg_byte_ptr == BLOCK_SIZE) { + h = sha256_compression(msg_block, h); + } + } + + let modulo = N % BLOCK_SIZE; + // Handle setup of the final msg block. + // This case is only hit if the msg is less than the block size, + // or our message cannot be evenly split into blocks. + if modulo != 0 { + let msg_start = BLOCK_SIZE * num_blocks; + /// Safety: the msg_block is checked below in verify_msg_block + let (new_msg_block, new_msg_byte_ptr) = + unsafe { build_msg_block(msg, message_size, msg_start) }; + + if msg_start < message_size { + msg_block = new_msg_block; + } + + if !is_unconstrained() { + let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start); + if msg_start < message_size { + msg_byte_ptr = new_msg_byte_ptr; + verify_msg_block_padding(msg_block, msg_byte_ptr); + } + } else if msg_start < message_size { + msg_byte_ptr = new_msg_byte_ptr; + } + } + + // If we had modulo == 0 then it means the last block was full, + // and we can reset the pointer to zero to overwrite it. + if msg_byte_ptr == BLOCK_SIZE { + msg_byte_ptr = 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]). + // Here we rely on the fact that everything beyond the available input is set to 0. + msg_block = update_block_item( + msg_block, + msg_byte_ptr, + |msg_item| set_item_byte_then_zeros(msg_item, msg_byte_ptr, 1 << 7), + ); + msg_byte_ptr = msg_byte_ptr + 1; + let last_block = msg_block; + + // If we don't have room to write the size, compress the block and reset it. + if msg_byte_ptr > MSG_SIZE_PTR { + h = sha256_compression(msg_block, h); + // `attach_len_to_msg_block` will zero out everything after the `msg_byte_ptr`. + msg_byte_ptr = 0; + } + + /// Safety: the msg_len is checked below in verify_msg_len + msg_block = unsafe { attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size) }; + + if !is_unconstrained() { + verify_msg_len(msg_block, last_block, msg_byte_ptr, message_size); + } + + hash_final_block(msg_block, h) +} + +// Take `BLOCK_SIZE` number of bytes from `msg` starting at `msg_start`. +// Returns the block and the length that has been copied rather than padded with zeros. +unconstrained fn build_msg_block( + msg: [u8; N], + message_size: u32, + msg_start: u32, +) -> (MSG_BLOCK, BLOCK_BYTE_PTR) { + let mut msg_block: MSG_BLOCK = [0; INT_BLOCK_SIZE]; + + // We insert `BLOCK_SIZE` bytes (or up to the end of the message) + let block_input = if msg_start + BLOCK_SIZE > message_size { + if message_size < msg_start { + // This function is sometimes called with `msg_start` past the end of the message. + // In this case we return an empty block and zero pointer to signal that the result should be ignored. + 0 + } else { + message_size - msg_start + } + } else { + BLOCK_SIZE + }; + + // Figure out the number of items in the int array that we have to pack. + // e.g. if the input is [0,1,2,3,4,5] then we need to pack it as 2 items: [0123, 4500] + let mut int_input = block_input / INT_SIZE; + if block_input % INT_SIZE != 0 { + int_input = int_input + 1; + }; + + for i in 0..int_input { + let mut msg_item: u32 = 0; + // Always construct the integer as 4 bytes, even if it means going beyond the input. + for j in 0..INT_SIZE { + let k = i * INT_SIZE + j; + let msg_byte = if k < block_input { + msg[msg_start + k] + } else { + 0 + }; + msg_item = lshift8(msg_item, 1) + msg_byte as u32; + } + msg_block[i] = msg_item; + } + + // Returning the index as if it was a 64 byte array. + // We have to project it down to 16 items and bit shifting to get a byte back if we need it. + (msg_block, block_input) +} + +// Verify the block we are compressing was appropriately constructed by `build_msg_block` +// and matches the input data. Returns the index of the first unset item. +// If `message_size` is less than `msg_start` then this is called with the old non-empty block; +// in that case we can skip verification, ie. no need to check that everything is zero. +fn verify_msg_block( + msg: [u8; N], + message_size: u32, + msg_block: MSG_BLOCK, + msg_start: u32, +) -> BLOCK_BYTE_PTR { + let mut msg_byte_ptr = 0; + let mut msg_end = msg_start + BLOCK_SIZE; + if msg_end > N { + msg_end = N; + } + // We might have to go beyond the input to pad the fields. + if msg_end % INT_SIZE != 0 { + msg_end = msg_end + INT_SIZE - msg_end % INT_SIZE; + } + + // Reconstructed packed item. + let mut msg_item: u32 = 0; + + // Inclusive at the end so that we can compare the last item. + let mut i: u32 = 0; + for k in msg_start..=msg_end { + if k % INT_SIZE == 0 { + // If we consumed some input we can compare against the block. + if (msg_start < message_size) & (k > msg_start) { + assert_eq(msg_block[i], msg_item as u32); + i = i + 1; + msg_item = 0; + } + } + // Shift the accumulator + msg_item = lshift8(msg_item, 1); + // If we have input to consume, add it at the rightmost position. + if k < message_size & k < msg_end { + msg_item = msg_item + msg[k] as u32; + msg_byte_ptr = msg_byte_ptr + 1; + } + } + + msg_byte_ptr +} + +// Verify the block we are compressing was appropriately padded with zeros by `build_msg_block`. +// This is only relevant for the last, potentially partially filled block. +fn verify_msg_block_padding(msg_block: MSG_BLOCK, msg_byte_ptr: BLOCK_BYTE_PTR) { + // Check all the way to the end of the block. + verify_msg_block_zeros(msg_block, msg_byte_ptr, INT_BLOCK_SIZE); +} + +// Verify that a region of ints in the message block are (partially) zeroed, +// up to an (exclusive) maximum which can either be the end of the block +// or just where the size is to be written. +fn verify_msg_block_zeros( + msg_block: MSG_BLOCK, + mut msg_byte_ptr: BLOCK_BYTE_PTR, + max_int_byte_ptr: u32, +) { + // This variable is used to get around the compiler under-constrained check giving a warning. + // We want to check against a constant zero, but if it does not come from the circuit inputs + // or return values the compiler check will issue a warning. + let zero = msg_block[0] - msg_block[0]; + + // First integer which is supposed to be (partially) zero. + let mut int_byte_ptr = msg_byte_ptr / INT_SIZE; + + // Check partial zeros. + let modulo = msg_byte_ptr % INT_SIZE; + if modulo != 0 { + let zeros = INT_SIZE - modulo; + let mask = if zeros == 3 { + TWO_POW_24 + } else if zeros == 2 { + TWO_POW_16 + } else { + TWO_POW_8 + }; + assert_eq(msg_block[int_byte_ptr] % mask, zero); + int_byte_ptr = int_byte_ptr + 1; + } + + // Check the rest of the items. + for i in 0..max_int_byte_ptr { + if i >= int_byte_ptr { + assert_eq(msg_block[i], zero); + } + } +} + +// Verify that up to the byte pointer the two blocks are equal. +// At the byte pointer the new block can be partially zeroed. +fn verify_msg_block_equals_last( + msg_block: MSG_BLOCK, + last_block: MSG_BLOCK, + mut msg_byte_ptr: BLOCK_BYTE_PTR, +) { + // msg_byte_ptr is the position at which they are no longer have to be the same. + // First integer which is supposed to be (partially) zero contains that pointer. + let mut int_byte_ptr = msg_byte_ptr / INT_SIZE; + + // Check partial zeros. + let modulo = msg_byte_ptr % INT_SIZE; + if modulo != 0 { + // Reconstruct the partially zero item from the last block. + let last_field = last_block[int_byte_ptr]; + let mut msg_item: u32 = 0; + // Reset to where they are still equal. + msg_byte_ptr = msg_byte_ptr - modulo; + for i in 0..INT_SIZE { + msg_item = lshift8(msg_item, 1); + if i < modulo { + msg_item = msg_item + get_item_byte(last_field, msg_byte_ptr) as u32; + msg_byte_ptr = msg_byte_ptr + 1; + } + } + assert_eq(msg_block[int_byte_ptr], msg_item); + } + + for i in 0..INT_SIZE_PTR { + if i < int_byte_ptr { + assert_eq(msg_block[i], last_block[i]); + } + } +} + +// Apply a function on the block item which the pointer indicates. +fn update_block_item( + mut msg_block: MSG_BLOCK, + msg_byte_ptr: BLOCK_BYTE_PTR, + f: fn[Env](u32) -> u32, +) -> MSG_BLOCK { + let i = msg_byte_ptr / INT_SIZE; + msg_block[i] = f(msg_block[i]); + msg_block +} + +// Set the rightmost `zeros` number of bytes to 0. +fn set_item_zeros(item: u32, zeros: u8) -> u32 { + lshift8(rshift8(item, zeros), zeros) +} + +// Replace one byte in the item with a value, and set everything after it to zero. +fn set_item_byte_then_zeros(msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR, msg_byte: u8) -> u32 { + let zeros = INT_SIZE - msg_byte_ptr % INT_SIZE; + let zeroed_item = set_item_zeros(msg_item, zeros as u8); + let new_item = byte_into_item(msg_byte, msg_byte_ptr); + zeroed_item + new_item +} + +// Get a byte of a message item according to its overall position in the `BLOCK_SIZE` space. +fn get_item_byte(mut msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR) -> u8 { + // How many times do we have to shift to the right to get to the position we want? + let max_shifts = INT_SIZE - 1; + let shifts = max_shifts - msg_byte_ptr % INT_SIZE; + msg_item = rshift8(msg_item, shifts as u8); + // At this point the byte we want is in the rightmost position. + msg_item as u8 +} + +// Project a byte into a position in a field based on the overall block pointer. +// For example putting 1 into pointer 5 would be 100, because overall we would +// have [____, 0100] with indexes [0123,4567]. +fn byte_into_item(msg_byte: u8, msg_byte_ptr: BLOCK_BYTE_PTR) -> u32 { + let mut msg_item = msg_byte as u32; + // How many times do we have to shift to the left to get to the position we want? + let max_shifts = INT_SIZE - 1; + let shifts = max_shifts - msg_byte_ptr % INT_SIZE; + lshift8(msg_item, shifts as u8) +} + +// Construct a field out of 4 bytes. +fn make_item(b0: u8, b1: u8, b2: u8, b3: u8) -> u32 { + let mut item = b0 as u32; + item = lshift8(item, 1) + b1 as u32; + item = lshift8(item, 1) + b2 as u32; + item = lshift8(item, 1) + b3 as u32; + item +} + +// Shift by 8 bits to the left between 0 and 4 times. +// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context, +// otherwise multiplies by 256. +fn lshift8(item: u32, shifts: u8) -> u32 { + if is_unconstrained() { + if item == 0 { + 0 + } else { + // Brillig wouldn't shift 0<<4 without overflow. + item << (8 * shifts) + } + } else { + // We can do a for loop up to INT_SIZE or an if-else. + if shifts == 0 { + item + } else if shifts == 1 { + item * TWO_POW_8 + } else if shifts == 2 { + item * TWO_POW_16 + } else if shifts == 3 { + item * TWO_POW_24 + } else { + // Doesn't make sense, but it's most likely called on 0 anyway. + 0 + } + } +} + +// Shift by 8 bits to the right between 0 and 4 times. +// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context, +// otherwise divides by 256. +fn rshift8(item: u32, shifts: u8) -> u32 { + if is_unconstrained() { + item >> (8 * shifts) + } else { + // Division wouldn't work on `Field`. + if shifts == 0 { + item + } else if shifts == 1 { + item / TWO_POW_8 + } else if shifts == 2 { + item / TWO_POW_16 + } else if shifts == 3 { + item / TWO_POW_24 + } else { + 0 + } + } +} + +// Zero out all bytes between the end of the message and where the length is appended, +// then write the length into the last 8 bytes of the block. +unconstrained fn attach_len_to_msg_block( + mut msg_block: MSG_BLOCK, + mut msg_byte_ptr: BLOCK_BYTE_PTR, + message_size: u32, +) -> MSG_BLOCK { + // We assume that `msg_byte_ptr` is less than 57 because if not then it is reset to zero before calling this function. + // In any case, fill blocks up with zeros until the last 64 bits (i.e. until msg_byte_ptr = 56). + // There can be one item which has to be partially zeroed. + let modulo = msg_byte_ptr % INT_SIZE; + if modulo != 0 { + // Index of the block in which we find the item we need to partially zero. + let i = msg_byte_ptr / INT_SIZE; + let zeros = INT_SIZE - modulo; + msg_block[i] = set_item_zeros(msg_block[i], zeros as u8); + msg_byte_ptr = msg_byte_ptr + zeros; + } + + // The rest can be zeroed without bit shifting anything. + for i in (msg_byte_ptr / INT_SIZE)..INT_SIZE_PTR { + msg_block[i] = 0; + } + + // Set the last two 4 byte ints as the first/second half of the 8 bytes of the length. + let len = 8 * message_size; + let len_bytes: [u8; 8] = (len as Field).to_be_bytes(); + for i in 0..=1 { + let shift = i * 4; + msg_block[INT_SIZE_PTR + i] = make_item( + len_bytes[shift], + len_bytes[shift + 1], + len_bytes[shift + 2], + len_bytes[shift + 3], + ); + } + msg_block +} + +// Verify that the message length was correctly written by `attach_len_to_msg_block`, +// and that everything between the byte pointer and the size pointer was zeroed, +// and that everything before the byte pointer was untouched. +fn verify_msg_len( + msg_block: MSG_BLOCK, + last_block: MSG_BLOCK, + msg_byte_ptr: BLOCK_BYTE_PTR, + message_size: u32, +) { + // Check zeros up to the size pointer. + verify_msg_block_zeros(msg_block, msg_byte_ptr, INT_SIZE_PTR); + + // Check that up to the pointer we match the last block. + verify_msg_block_equals_last(msg_block, last_block, msg_byte_ptr); + + // We verify the message length was inserted correctly by reversing the byte decomposition. + let mut reconstructed_len: u64 = 0; + for i in INT_SIZE_PTR..INT_BLOCK_SIZE { + reconstructed_len = reconstructed_len * TWO_POW_32; + reconstructed_len = reconstructed_len + msg_block[i] as u64; + } + let len = 8 * message_size as u64; + assert_eq(reconstructed_len, len); +} + +// Perform the final compression, then transform the `STATE` into `HASH`. +fn hash_final_block(msg_block: MSG_BLOCK, mut state: STATE) -> HASH { + let mut out_h: HASH = [0; 32]; // Digest as sequence of bytes + // Hash final padded block + state = sha256_compression(msg_block, state); + + // Return final hash as byte array + for j in 0..8 { + let h_bytes: [u8; 4] = (state[j] as Field).to_be_bytes(); + for k in 0..4 { + out_h[4 * j + k] = h_bytes[k]; + } + } + + out_h +} + +mod tests { + use super::{ + attach_len_to_msg_block, build_msg_block, byte_into_item, get_item_byte, make_item, + set_item_byte_then_zeros, set_item_zeros, + }; + use super::INT_BLOCK; + use super::sha256_var; + + #[test] + fn smoke_test() { + let input = [0xbd]; + let result = [ + 0x68, 0x32, 0x57, 0x20, 0xaa, 0xbd, 0x7c, 0x82, 0xf3, 0x0f, 0x55, 0x4b, 0x31, 0x3d, + 0x05, 0x70, 0xc9, 0x5a, 0xcc, 0xbb, 0x7d, 0xc4, 0xb5, 0xaa, 0xe1, 0x12, 0x04, 0xc0, + 0x8f, 0xfe, 0x73, 0x2b, + ]; + assert_eq(sha256_var(input, input.len() as u64), result); + } + + #[test] + fn msg_just_over_block() { + let input = [ + 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, + 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, + 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, + 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, + ]; + let result = [ + 91, 122, 146, 93, 52, 109, 133, 148, 171, 61, 156, 70, 189, 238, 153, 7, 222, 184, 94, + 24, 65, 114, 192, 244, 207, 199, 87, 232, 192, 224, 171, 207, + ]; + assert_eq(sha256_var(input, input.len() as u64), result); + } + + #[test] + fn msg_multiple_over_block() { + let input = [ + 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, + 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, + 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, + 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 115, 45, 97, 115, + 99, 105, 105, 13, 10, 109, 105, 109, 101, 45, 118, 101, 114, 115, 105, 111, 110, 58, 49, + 46, 48, 32, 40, 77, 97, 99, 32, 79, 83, 32, 88, 32, 77, 97, 105, 108, 32, 49, 54, 46, + 48, 32, 92, 40, 51, 55, 51, 49, 46, 53, 48, 48, 46, 50, 51, 49, 92, 41, 41, 13, 10, 115, + 117, 98, 106, 101, 99, 116, 58, 72, 101, 108, 108, 111, 13, 10, 109, 101, 115, 115, 97, + 103, 101, 45, 105, 100, 58, 60, 56, 70, 56, 49, 57, 68, 51, 50, 45, 66, 54, 65, 67, 45, + 52, 56, 57, 68, 45, 57, 55, 55, 70, 45, 52, 51, 56, 66, 66, 67, 52, 67, 65, 66, 50, 55, + 64, 109, 101, 46, 99, 111, 109, 62, 13, 10, 100, 97, 116, 101, 58, 83, 97, 116, 44, 32, + 50, 54, 32, 65, 117, 103, 32, 50, 48, 50, 51, 32, 49, 50, 58, 50, 53, 58, 50, 50, 32, + 43, 48, 52, 48, 48, 13, 10, 116, 111, 58, 122, 107, 101, 119, 116, 101, 115, 116, 64, + 103, 109, 97, 105, 108, 46, 99, 111, 109, 13, 10, 100, 107, 105, 109, 45, 115, 105, 103, + 110, 97, 116, 117, 114, 101, 58, 118, 61, 49, 59, 32, 97, 61, 114, 115, 97, 45, 115, + 104, 97, 50, 53, 54, 59, 32, 99, 61, 114, 101, 108, 97, 120, 101, 100, 47, 114, 101, + 108, 97, 120, 101, 100, 59, 32, 100, 61, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, + 59, 32, 115, 61, 49, 97, 49, 104, 97, 105, 59, 32, 116, 61, 49, 54, 57, 51, 48, 51, 56, + 51, 51, 55, 59, 32, 98, 104, 61, 55, 120, 81, 77, 68, 117, 111, 86, 86, 85, 52, 109, 48, + 87, 48, 87, 82, 86, 83, 114, 86, 88, 77, 101, 71, 83, 73, 65, 83, 115, 110, 117, 99, 75, + 57, 100, 74, 115, 114, 99, 43, 118, 85, 61, 59, 32, 104, 61, 102, 114, 111, 109, 58, 67, + 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 77, 105, 109, 101, 45, 86, 101, + 114, 115, 105, 111, 110, 58, 83, 117, 98, 106, 101, 99, + ]; + let result = [ + 116, 90, 151, 31, 78, 22, 138, 180, 211, 189, 69, 76, 227, 200, 155, 29, 59, 123, 154, + 60, 47, 153, 203, 129, 157, 251, 48, 2, 79, 11, 65, 47, + ]; + assert_eq(sha256_var(input, input.len() as u64), result); + } + + #[test] + fn msg_just_under_block() { + let input = [ + 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, + 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, + 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, + 108, 97, 105, 110, 59, + ]; + let result = [ + 143, 140, 76, 173, 222, 123, 102, 68, 70, 149, 207, 43, 39, 61, 34, 79, 216, 252, 213, + 165, 74, 16, 110, 74, 29, 64, 138, 167, 30, 1, 9, 119, + ]; + assert_eq(sha256_var(input, input.len() as u64), result); + } + + #[test] + fn msg_big_not_block_multiple() { + let input = [ + 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, + 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, + 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, + 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 115, 45, 97, 115, + 99, 105, 105, 13, 10, 109, 105, 109, 101, 45, 118, 101, 114, 115, 105, 111, 110, 58, 49, + 46, 48, 32, 40, 77, 97, 99, 32, 79, 83, 32, 88, 32, 77, 97, 105, 108, 32, 49, 54, 46, + 48, 32, 92, 40, 51, 55, 51, 49, 46, 53, 48, 48, 46, 50, 51, 49, 92, 41, 41, 13, 10, 115, + 117, 98, 106, 101, 99, 116, 58, 72, 101, 108, 108, 111, 13, 10, 109, 101, 115, 115, 97, + 103, 101, 45, 105, 100, 58, 60, 56, 70, 56, 49, 57, 68, 51, 50, 45, 66, 54, 65, 67, 45, + 52, 56, 57, 68, 45, 57, 55, 55, 70, 45, 52, 51, 56, 66, 66, 67, 52, 67, 65, 66, 50, 55, + 64, 109, 101, 46, 99, 111, 109, 62, 13, 10, 100, 97, 116, 101, 58, 83, 97, 116, 44, 32, + 50, 54, 32, 65, 117, 103, 32, 50, 48, 50, 51, 32, 49, 50, 58, 50, 53, 58, 50, 50, 32, + 43, 48, 52, 48, 48, 13, 10, 116, 111, 58, 122, 107, 101, 119, 116, 101, 115, 116, 64, + 103, 109, 97, 105, 108, 46, 99, 111, 109, 13, 10, 100, 107, 105, 109, 45, 115, 105, 103, + 110, 97, 116, 117, 114, 101, 58, 118, 61, 49, 59, 32, 97, 61, 114, 115, 97, 45, 115, + 104, 97, 50, 53, 54, 59, 32, 99, 61, 114, 101, 108, 97, 120, 101, 100, 47, 114, 101, + 108, 97, 120, 101, 100, 59, 32, 100, 61, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, + 59, 32, 115, 61, 49, 97, 49, 104, 97, 105, 59, 32, 116, 61, 49, 54, 57, 51, 48, 51, 56, + 51, 51, 55, 59, 32, 98, 104, 61, 55, 120, 81, 77, 68, 117, 111, 86, 86, 85, 52, 109, 48, + 87, 48, 87, 82, 86, 83, 114, 86, 88, 77, 101, 71, 83, 73, 65, 83, 115, 110, 117, 99, 75, + 57, 100, 74, 115, 114, 99, 43, 118, 85, 61, 59, 32, 104, 61, 102, 114, 111, 109, 58, 67, + 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 77, 105, 109, 101, 45, 86, 101, + 114, 115, 105, 111, 110, 58, 83, 117, 98, 106, 101, 99, 116, 58, 77, 101, 115, 115, 97, + 103, 101, 45, 73, 100, 58, 68, 97, 116, 101, 58, 116, 111, 59, 32, 98, 61, + ]; + let result = [ + 112, 144, 73, 182, 208, 98, 9, 238, 54, 229, 61, 145, 222, 17, 72, 62, 148, 222, 186, + 55, 192, 82, 220, 35, 66, 47, 193, 200, 22, 38, 26, 186, + ]; + assert_eq(sha256_var(input, input.len() as u64), result); + } + + #[test] + fn msg_big_with_padding() { + let input = [ + 48, 130, 1, 37, 2, 1, 0, 48, 11, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 48, 130, 1, 17, + 48, 37, 2, 1, 1, 4, 32, 176, 223, 31, 133, 108, 84, 158, 102, 70, 11, 165, 175, 196, 12, + 201, 130, 25, 131, 46, 125, 156, 194, 28, 23, 55, 133, 157, 164, 135, 136, 220, 78, 48, + 37, 2, 1, 2, 4, 32, 190, 82, 180, 235, 222, 33, 79, 50, 152, 136, 142, 35, 116, 224, 6, + 242, 156, 141, 128, 248, 10, 61, 98, 86, 248, 45, 207, 210, 90, 232, 175, 38, 48, 37, 2, + 1, 3, 4, 32, 0, 194, 104, 108, 237, 246, 97, 230, 116, 198, 69, 110, 26, 87, 17, 89, + 110, 199, 108, 250, 36, 21, 39, 87, 110, 102, 250, 213, 174, 131, 171, 174, 48, 37, 2, + 1, 11, 4, 32, 136, 155, 87, 144, 111, 15, 152, 127, 85, 25, 154, 81, 20, 58, 51, 75, + 193, 116, 234, 0, 60, 30, 29, 30, 183, 141, 72, 247, 255, 203, 100, 124, 48, 37, 2, 1, + 12, 4, 32, 41, 234, 106, 78, 31, 11, 114, 137, 237, 17, 92, 71, 134, 47, 62, 78, 189, + 233, 201, 214, 53, 4, 47, 189, 201, 133, 6, 121, 34, 131, 64, 142, 48, 37, 2, 1, 13, 4, + 32, 91, 222, 210, 193, 62, 222, 104, 82, 36, 41, 138, 253, 70, 15, 148, 208, 156, 45, + 105, 171, 241, 195, 185, 43, 217, 162, 146, 201, 222, 89, 238, 38, 48, 37, 2, 1, 14, 4, + 32, 76, 123, 216, 13, 51, 227, 72, 245, 59, 193, 238, 166, 103, 49, 23, 164, 171, 188, + 194, 197, 156, 187, 249, 28, 198, 95, 69, 15, 182, 56, 54, 38, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 result = [ + 32, 85, 108, 174, 127, 112, 178, 182, 8, 43, 134, 123, 192, 211, 131, 66, 184, 240, 212, + 181, 240, 180, 106, 195, 24, 117, 54, 129, 19, 10, 250, 53, + ]; + let message_size = 297; + assert_eq(sha256_var(input, message_size), result); + } + + #[test] + fn msg_big_no_padding() { + let input = [ + 48, 130, 1, 37, 2, 1, 0, 48, 11, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 48, 130, 1, 17, + 48, 37, 2, 1, 1, 4, 32, 176, 223, 31, 133, 108, 84, 158, 102, 70, 11, 165, 175, 196, 12, + 201, 130, 25, 131, 46, 125, 156, 194, 28, 23, 55, 133, 157, 164, 135, 136, 220, 78, 48, + 37, 2, 1, 2, 4, 32, 190, 82, 180, 235, 222, 33, 79, 50, 152, 136, 142, 35, 116, 224, 6, + 242, 156, 141, 128, 248, 10, 61, 98, 86, 248, 45, 207, 210, 90, 232, 175, 38, 48, 37, 2, + 1, 3, 4, 32, 0, 194, 104, 108, 237, 246, 97, 230, 116, 198, 69, 110, 26, 87, 17, 89, + 110, 199, 108, 250, 36, 21, 39, 87, 110, 102, 250, 213, 174, 131, 171, 174, 48, 37, 2, + 1, 11, 4, 32, 136, 155, 87, 144, 111, 15, 152, 127, 85, 25, 154, 81, 20, 58, 51, 75, + 193, 116, 234, 0, 60, 30, 29, 30, 183, 141, 72, 247, 255, 203, 100, 124, 48, 37, 2, 1, + 12, 4, 32, 41, 234, 106, 78, 31, 11, 114, 137, 237, 17, 92, 71, 134, 47, 62, 78, 189, + 233, 201, 214, 53, 4, 47, 189, 201, 133, 6, 121, 34, 131, 64, 142, 48, 37, 2, 1, 13, 4, + 32, 91, 222, 210, 193, 62, 222, 104, 82, 36, 41, 138, 253, 70, 15, 148, 208, 156, 45, + 105, 171, 241, 195, 185, 43, 217, 162, 146, 201, 222, 89, 238, 38, 48, 37, 2, 1, 14, 4, + 32, 76, 123, 216, 13, 51, 227, 72, 245, 59, 193, 238, 166, 103, 49, 23, 164, 171, 188, + 194, 197, 156, 187, 249, 28, 198, 95, 69, 15, 182, 56, 54, 38, + ]; + let result = [ + 32, 85, 108, 174, 127, 112, 178, 182, 8, 43, 134, 123, 192, 211, 131, 66, 184, 240, 212, + 181, 240, 180, 106, 195, 24, 117, 54, 129, 19, 10, 250, 53, + ]; + assert_eq(sha256_var(input, input.len() as u64), result); + } + + #[test] + fn same_msg_len_variable_padding() { + let input = [ + 29, 81, 165, 84, 243, 114, 101, 37, 242, 146, 127, 99, 69, 145, 39, 72, 213, 39, 253, + 179, 218, 37, 217, 201, 172, 93, 198, 50, 249, 70, 15, 30, 162, 112, 187, 40, 140, 9, + 236, 53, 32, 44, 38, 163, 113, 254, 192, 197, 44, 89, 71, 130, 169, 242, 17, 211, 214, + 72, 19, 178, 186, 168, 147, 127, 99, 101, 252, 227, 8, 147, 150, 85, 97, 158, 17, 107, + 218, 244, 82, 113, 247, 91, 208, 214, 60, 244, 87, 137, 173, 201, 130, 18, 66, 56, 198, + 149, 207, 189, 175, 120, 123, 224, 177, 167, 251, 159, 143, 110, 68, 183, 189, 70, 126, + 32, 35, 164, 44, 30, 44, 12, 65, 18, 62, 239, 242, 2, 248, 104, 2, 178, 64, 28, 126, 36, + 137, 24, 14, 116, 91, 98, 90, 159, 218, 102, 45, 11, 110, 223, 245, 184, 52, 99, 59, + 245, 136, 175, 3, 72, 164, 146, 145, 116, 22, 66, 24, 49, 193, 121, 3, 60, 37, 41, 97, + 3, 190, 66, 195, 225, 63, 46, 3, 118, 4, 208, 15, 1, 40, 254, 235, 151, 123, 70, 180, + 170, 44, 172, 90, 4, 254, 53, 239, 116, 246, 67, 56, 129, 61, 22, 169, 213, 65, 27, 216, + 116, 162, 239, 214, 207, 126, 177, 20, 100, 25, 48, 143, 84, 215, 70, 197, 53, 65, 70, + 86, 172, 61, 62, 9, 212, 167, 169, 133, 41, 126, 213, 196, 33, 192, 238, 0, 63, 246, + 215, 58, 128, 110, 101, 92, 3, 170, 214, 130, 149, 52, 81, 125, 118, 233, 3, 118, 193, + 104, 207, 120, 115, 77, 253, 191, 122, 0, 107, 164, 207, 113, 81, 169, 36, 201, 228, 74, + 134, 131, 218, 178, 35, 30, 216, 101, 2, 103, 174, 87, 95, 50, 50, 215, 157, 5, 210, + 188, 54, 211, 78, 45, 199, 96, 121, 241, 241, 176, 226, 194, 134, 130, 89, 217, 210, + 186, 32, 140, 39, 91, 103, 212, 26, 87, 32, 72, 144, 228, 230, 117, 99, 188, 50, 15, 69, + 79, 179, 50, 12, 106, 86, 218, 101, 73, 142, 243, 29, 250, 122, 228, 233, 29, 255, 22, + 121, 114, 125, 103, 41, 250, 241, 179, 126, 158, 198, 116, 209, 65, 94, 98, 228, 175, + 169, 96, 3, 9, 233, 133, 214, 55, 161, 164, 103, 80, 85, 24, 186, 64, 167, 92, 131, 53, + 101, 202, 47, 25, 104, 118, 155, 14, 12, 12, 25, 116, 45, 221, 249, 28, 246, 212, 200, + 157, 167, 169, 56, 197, 181, 4, 245, 146, 1, 140, 234, 191, 212, 228, 125, 87, 81, 86, + 119, 30, 63, 129, 143, 32, 96, + ]; + + // Prepare inputs of different lengths + let mut input_511 = [0; 511]; + let mut input_512 = [0; 512]; // Next block + let mut input_575 = [0; 575]; + let mut input_576 = [0; 576]; // Next block + for i in 0..input.len() { + input_511[i] = input[i]; + input_512[i] = input[i]; + input_575[i] = input[i]; + input_576[i] = input[i]; + } + + // Compute hashes of all inputs (with same message length) + let fixed_length_hash = super::sha256(input); + let var_full_length_hash = sha256_var(input, input.len() as u64); + let var_length_hash_511 = sha256_var(input_511, input.len() as u64); + let var_length_hash_512 = sha256_var(input_512, input.len() as u64); + let var_length_hash_575 = sha256_var(input_575, input.len() as u64); + let var_length_hash_576 = sha256_var(input_576, input.len() as u64); + + // All of the above should have produced the same hash + assert_eq(var_full_length_hash, fixed_length_hash); + assert_eq(var_length_hash_511, fixed_length_hash); + assert_eq(var_length_hash_512, fixed_length_hash); + assert_eq(var_length_hash_575, fixed_length_hash); + assert_eq(var_length_hash_576, fixed_length_hash); + } + + #[test] + fn test_get_item_byte() { + let fld = make_item(10, 20, 30, 40); + assert_eq(fld, 0x0a141e28); + assert_eq(get_item_byte(fld, 0), 10); + assert_eq(get_item_byte(fld, 4), 10); + assert_eq(get_item_byte(fld, 6), 30); + } + + #[test] + fn test_byte_into_item() { + let fld = make_item(0, 20, 0, 0); + assert_eq(byte_into_item(20, 1), fld); + assert_eq(byte_into_item(20, 5), fld); + } + + #[test] + fn test_set_item_zeros() { + let fld0 = make_item(10, 20, 30, 40); + let fld1 = make_item(10, 0, 0, 0); + assert_eq(set_item_zeros(fld0, 3), fld1); + assert_eq(set_item_zeros(fld0, 4), 0); + assert_eq(set_item_zeros(0, 4), 0); + } + + #[test] + fn test_set_item_byte_then_zeros() { + let fld0 = make_item(10, 20, 30, 40); + let fld1 = make_item(10, 50, 0, 0); + assert_eq(set_item_byte_then_zeros(fld0, 1, 50), fld1); + } + + #[test] + fn test_build_msg_block_start_0() { + let input = [ + 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, + 101, 115, 46, 48, + ]; + assert_eq(input.len(), 22); + + /// Safety: testing context + let (msg_block, msg_byte_ptr) = unsafe { build_msg_block(input, input.len(), 0) }; + assert_eq(msg_byte_ptr, input.len()); + assert_eq(msg_block[0], make_item(input[0], input[1], input[2], input[3])); + assert_eq(msg_block[1], make_item(input[4], input[5], input[6], input[7])); + assert_eq(msg_block[5], make_item(input[20], input[21], 0, 0)); + assert_eq(msg_block[6], 0); + } + + #[test] + fn test_build_msg_block_start_1() { + let input = [ + 102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, + 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, + 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, + 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, + ]; + assert_eq(input.len(), 68); + /// Safety: test context + let (msg_block, msg_byte_ptr) = unsafe { build_msg_block(input, input.len(), 64) }; + assert_eq(msg_byte_ptr, 4); + assert_eq(msg_block[0], make_item(input[64], input[65], input[66], input[67])); + assert_eq(msg_block[1], 0); + } + + #[test] + fn test_attach_len_to_msg_block() { + let input: INT_BLOCK = [ + 2152555847, 1397309779, 1936618851, 1262052426, 1936876331, 1985297723, 543702374, + 1919905082, 1131376244, 1701737517, 1417244773, 978151789, 1697470053, 1920166255, + 1849316213, 1651139939, + ]; + /// Safety: testing context + let msg_block = unsafe { attach_len_to_msg_block(input, 1, 448) }; + assert_eq(msg_block[0], ((1 << 7) as u32) * 256 * 256 * 256); + assert_eq(msg_block[1], 0); + assert_eq(msg_block[15], 3584); + } +} diff --git a/noir_stdlib/src/hash/sha512.nr b/noir_stdlib/src/hash/sha512.nr new file mode 100644 index 00000000000..5630139c1f1 --- /dev/null +++ b/noir_stdlib/src/hash/sha512.nr @@ -0,0 +1,165 @@ +// Implementation of SHA-512 mapping a byte array of variable length to +// 64 bytes. +// Internal functions act on 64-bit unsigned integers for simplicity. +// Auxiliary mappings; names as in FIPS PUB 180-4 +fn rotr64(a: u64, b: 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. + (a >> b) + (a << (64 - b)) +} + +fn sha_ch(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (!x & z) +} + +fn sha_maj(x: u64, y: u64, z: u64) -> u64 { + (x & y) ^ (x & z) ^ (y & z) +} + +fn sha_bigma0(x: u64) -> u64 { + rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39) +} + +fn sha_bigma1(x: u64) -> u64 { + rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41) +} + +fn sha_sigma0(x: u64) -> u64 { + rotr64(x, 1) ^ rotr64(x, 8) ^ (x >> 7) +} + +fn sha_sigma1(x: u64) -> u64 { + rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6) +} + +fn sha_w(msg: [u64; 16]) -> [u64; 80] // Expanded message blocks +{ + let mut w: [u64; 80] = [0; 80]; + + for j in 0..16 { + w[j] = msg[j]; + } + + for j in 16..80 { + w[j] = crate::wrapping_add( + crate::wrapping_add(sha_sigma1(w[j - 2]), w[j - 7]), + crate::wrapping_add(sha_sigma0(w[j - 15]), w[j - 16]), + ); + } + w +} + +// SHA-512 compression function +#[no_predicates] +fn sha_c(msg: [u64; 16], hash: [u64; 8]) -> [u64; 8] { + // noir-fmt:ignore + let K: [u64; 80] = [4794697086780616226, 8158064640168781261, 13096744586834688815, 16840607885511220156, 4131703408338449720, 6480981068601479193, 10538285296894168987, 12329834152419229976, 15566598209576043074, 1334009975649890238, 2608012711638119052, 6128411473006802146, 8268148722764581231, 9286055187155687089, 11230858885718282805, 13951009754708518548, 16472876342353939154, 17275323862435702243, 1135362057144423861, 2597628984639134821, 3308224258029322869, 5365058923640841347, 6679025012923562964, 8573033837759648693, 10970295158949994411, 12119686244451234320, 12683024718118986047, 13788192230050041572, 14330467153632333762, 15395433587784984357, 489312712824947311, 1452737877330783856, 2861767655752347644, 3322285676063803686, 5560940570517711597, 5996557281743188959, 7280758554555802590, 8532644243296465576, 9350256976987008742, 10552545826968843579, 11727347734174303076, 12113106623233404929, 14000437183269869457, 14369950271660146224, 15101387698204529176, 15463397548674623760, 17586052441742319658, 1182934255886127544, 1847814050463011016, 2177327727835720531, 2830643537854262169, 3796741975233480872, 4115178125766777443, 5681478168544905931, 6601373596472566643, 7507060721942968483, 8399075790359081724, 8693463985226723168, 9568029438360202098, 10144078919501101548, 10430055236837252648, 11840083180663258601, 13761210420658862357, 14299343276471374635, 14566680578165727644, 15097957966210449927, 16922976911328602910, 17689382322260857208, 500013540394364858, 748580250866718886, 1242879168328830382, 1977374033974150939, 2944078676154940804, 3659926193048069267, 4368137639120453308, 4836135668995329356, 5532061633213252278, 6448918945643986474, 6902733635092675308, 7801388544844847127]; // first 64 bits of fractional parts of cube roots of first 80 primes + let mut out_h: [u64; 8] = hash; + let w = sha_w(msg); + for j in 0..80 { + let out1 = crate::wrapping_add(out_h[7], sha_bigma1(out_h[4])); + let out2 = crate::wrapping_add(out1, sha_ch(out_h[4], out_h[5], out_h[6])); + let t1 = crate::wrapping_add(crate::wrapping_add(out2, K[j]), w[j]); + let t2 = crate::wrapping_add(sha_bigma0(out_h[0]), sha_maj(out_h[0], out_h[1], out_h[2])); + out_h[7] = out_h[6]; + out_h[6] = out_h[5]; + out_h[5] = out_h[4]; + out_h[4] = crate::wrapping_add(out_h[3], t1); + out_h[3] = out_h[2]; + out_h[2] = out_h[1]; + out_h[1] = out_h[0]; + out_h[0] = crate::wrapping_add(t1, t2); + } + + out_h +} +// Convert 128-byte array to array of 16 u64s +fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] { + let mut msg64: [u64; 16] = [0; 16]; + + for i in 0..16 { + let mut msg_field: Field = 0; + for j in 0..8 { + msg_field = msg_field * 256 + msg[128 - 8 * (i + 1) + j] as Field; + } + msg64[15 - i] = msg_field as u64; + } + + msg64 +} +// SHA-512 hash function +pub fn digest(msg: [u8; N]) -> [u8; 64] { + let mut msg_block: [u8; 128] = [0; 128]; + // noir-fmt:ignore + let mut h: [u64; 8] = [7640891576956012808, 13503953896175478587, 4354685564936845355, 11912009170470909681, 5840696475078001361, 11170449401992604703, 2270897969802886507, 6620516959819538809]; // Intermediate hash, starting with the canonical initial value + let mut c: [u64; 8] = [0; 8]; // Compression of current message block as sequence of u64 + let mut out_h: [u8; 64] = [0; 64]; // Digest as sequence of bytes + let mut i: u64 = 0; // Message byte pointer + for k in 0..msg.len() { + // Populate msg_block + msg_block[i] = msg[k]; + i = i + 1; + if i == 128 { + // Enough to hash block + c = sha_c(msg_u8_to_u64(msg_block), h); + for j in 0..8 { + h[j] = crate::wrapping_add(h[j], c[j]); + } + + i = 0; + } + } + // Pad the rest such that we have a [u64; 2] block at the end representing the length + // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). + msg_block[i] = 1 << 7; + i += 1; + // If i >= 113, there aren't enough bits in the current message block to accomplish this, so + // the 1 and 0s fill up the current block, which we then compress accordingly. + if i >= 113 { + // Not enough bits (128) to store length. Fill up with zeros. + if i < 128 { + for _i in 113..128 { + if i <= 127 { + msg_block[i] = 0; + i += 1; + } + } + } + c = sha_c(msg_u8_to_u64(msg_block), h); + for j in 0..8 { + h[j] = crate::wrapping_add(h[j], c[j]); + } + + i = 0; + } + + let len = 8 * msg.len(); + let len_bytes: [u8; 16] = (len as Field).to_le_bytes(); + 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] = 0; + i += 1; + } else if i < 128 { + for j in 0..16 { + msg_block[127 - j] = len_bytes[j]; + } + i += 16; // Done. + } + } + // Hash final padded block + c = sha_c(msg_u8_to_u64(msg_block), h); + for j in 0..8 { + h[j] = crate::wrapping_add(h[j], c[j]); + } + // Return final hash as byte array + for j in 0..8 { + let h_bytes: [u8; 8] = (h[7 - j] as Field).to_le_bytes(); + for k in 0..8 { + out_h[63 - 8 * j - k] = h_bytes[k]; + } + } + + out_h +} diff --git a/noir_stdlib/src/hint.nr b/noir_stdlib/src/hint.nr new file mode 100644 index 00000000000..25dcc7ec56e --- /dev/null +++ b/noir_stdlib/src/hint.nr @@ -0,0 +1,6 @@ +/// An identity function that *hints* to the compiler to be maximally pessimistic about what `black_box` could do. +/// +/// This can be used to block the SSA optimization passes being applied to a value, which should help to prevent +/// test programs from being optimized down to nothing and have them resemble runtime code more closely. +#[builtin(black_box)] +pub fn black_box(value: T) -> T {} diff --git a/noir_stdlib/src/lib.nr b/noir_stdlib/src/lib.nr new file mode 100644 index 00000000000..fb073516d29 --- /dev/null +++ b/noir_stdlib/src/lib.nr @@ -0,0 +1,129 @@ +pub mod hash; +pub mod aes128; +pub mod array; +pub mod slice; +pub mod merkle; +pub mod ecdsa_secp256k1; +pub mod ecdsa_secp256r1; +pub mod embedded_curve_ops; +pub mod sha256; +pub mod sha512; +pub mod field; +pub mod collections; +pub mod compat; +pub mod convert; +pub mod option; +pub mod string; +pub mod test; +pub mod cmp; +pub mod ops; +pub mod default; +pub mod prelude; +pub mod uint128; +pub mod bigint; +pub mod runtime; +pub mod meta; +pub mod append; +pub mod mem; +pub mod panic; +pub mod hint; + +use convert::AsPrimitive; + +// Oracle calls are required to be wrapped in an unconstrained function +// Thus, the only argument to the `println` oracle is expected to always be an ident +#[oracle(print)] +unconstrained fn print_oracle(with_newline: bool, input: T) {} + +unconstrained fn print_unconstrained(with_newline: bool, input: T) { + print_oracle(with_newline, input); +} + +pub fn println(input: T) { + /// Safety: a print statement cannot be constrained + unsafe { + print_unconstrained(true, input); + } +} + +pub fn print(input: T) { + /// Safety: a print statement cannot be constrained + unsafe { + print_unconstrained(false, input); + } +} + +pub fn verify_proof( + verification_key: [Field; N], + proof: [Field; M], + public_inputs: [Field; K], + key_hash: Field, +) { + verify_proof_internal(verification_key, proof, public_inputs, key_hash, 0); +} + +pub fn verify_proof_with_type( + verification_key: [Field; N], + proof: [Field; M], + public_inputs: [Field; K], + key_hash: Field, + proof_type: u32, +) { + if !crate::runtime::is_unconstrained() { + crate::assert_constant(proof_type); + } + verify_proof_internal(verification_key, proof, public_inputs, key_hash, proof_type); +} + +#[foreign(recursive_aggregation)] +fn verify_proof_internal( + verification_key: [Field; N], + proof: [Field; M], + public_inputs: [Field; K], + key_hash: Field, + proof_type: u32, +) {} + +// Asserts that the given value is known at compile-time. +// Useful for debugging for-loop bounds. +#[builtin(assert_constant)] +pub fn assert_constant(x: T) {} + +// Asserts that the given value is both true and known at compile-time +#[builtin(static_assert)] +pub fn static_assert(predicate: bool, message: str) {} + +pub fn wrapping_add(x: T, y: T) -> T +where + T: AsPrimitive, + Field: AsPrimitive, +{ + AsPrimitive::as_(x.as_() + y.as_()) +} + +pub fn wrapping_sub(x: T, y: T) -> T +where + T: AsPrimitive, + Field: AsPrimitive, +{ + //340282366920938463463374607431768211456 is 2^128, it is used to avoid underflow + AsPrimitive::as_(x.as_() + 340282366920938463463374607431768211456 - y.as_()) +} + +pub fn wrapping_mul(x: T, y: T) -> T +where + T: AsPrimitive, + Field: AsPrimitive, +{ + AsPrimitive::as_(x.as_() * y.as_()) +} + +#[builtin(as_witness)] +pub fn as_witness(x: Field) {} + +mod tests { + #[test(should_fail_with = "custom message")] + fn test_static_assert_custom_message() { + super::static_assert(1 == 2, "custom message"); + } +} diff --git a/noir_stdlib/src/mem.nr b/noir_stdlib/src/mem.nr new file mode 100644 index 00000000000..23125867eab --- /dev/null +++ b/noir_stdlib/src/mem.nr @@ -0,0 +1,31 @@ +/// For any type, return an instance of that type by initializing +/// all of its fields to 0. This is considered to be unsafe since there +/// is no guarantee that all zeroes is a valid bit pattern for every type. +#[builtin(zeroed)] +pub fn zeroed() -> T {} + +/// Transmutes a value of type T to a value of type U. +/// +/// Both types are asserted to be equal during compilation but after type checking. +/// If not, a compilation error is issued. +/// +/// This function is useful for types using arithmetic generics in cases +/// which the compiler otherwise cannot prove equal during type checking. +/// You can use this to obtain a value of the correct type while still asserting +/// that it is equal to the previous. +#[builtin(checked_transmute)] +pub fn checked_transmute(value: T) -> U {} + +/// Returns the internal reference count of an array value in unconstrained code. +/// +/// Arrays only have reference count in unconstrained code - using this anywhere +/// else will return zero. +#[builtin(array_refcount)] +pub fn array_refcount(array: [T; N]) -> u32 {} + +/// Returns the internal reference count of a slice value in unconstrained code. +/// +/// Slices only have reference count in unconstrained code - using this anywhere +/// else will return zero. +#[builtin(slice_refcount)] +pub fn slice_refcount(slice: [T]) -> u32 {} diff --git a/noir_stdlib/src/merkle.nr b/noir_stdlib/src/merkle.nr new file mode 100644 index 00000000000..f6806874444 --- /dev/null +++ b/noir_stdlib/src/merkle.nr @@ -0,0 +1,18 @@ +// Regular merkle tree means a append-only merkle tree (Explain why this is the only way to have privacy and alternatives if you don't want it) +// Currently we assume that it is a binary tree, so depth k implies a width of 2^k +// XXX: In the future we can add an arity parameter +// Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function. +pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field { + let index_bits: [u1; N] = index.to_le_bits(); + let mut current = leaf; + for i in 0..N { + let path_bit = index_bits[i] as bool; + let (hash_left, hash_right) = if path_bit { + (hash_path[i], current) + } else { + (current, hash_path[i]) + }; + current = crate::hash::pedersen_hash([hash_left, hash_right]); + } + current +} diff --git a/noir_stdlib/src/meta/ctstring.nr b/noir_stdlib/src/meta/ctstring.nr new file mode 100644 index 00000000000..e23567ece7d --- /dev/null +++ b/noir_stdlib/src/meta/ctstring.nr @@ -0,0 +1,102 @@ +use crate::append::Append; + +impl CtString { + // docs:start:new + pub comptime fn new() -> Self { + // docs:end:new + "".as_ctstring() + } + + // Bug: using &mut self as the object results in this method not being found + // docs:start:append_str + pub comptime fn append_str(self, s: str) -> Self { + // docs:end:append_str + f"{self}{s}".as_ctstring() + } + + // docs:start:append_fmtstr + pub comptime fn append_fmtstr(self, s: fmtstr) -> Self { + // docs:end:append_fmtstr + f"{self}{s}".as_ctstring() + } + + /// CtString cannot directly return a str since the size would not be known. + /// To get around this, we return a quoted str and the underlying str can + /// be accessed using macro insertion `foo.as_quoted_str!()`. + // docs:start:as_quoted_str + pub comptime fn as_quoted_str(self) -> Quoted { + // docs:end:as_quoted_str + quote { $self } + } +} + +impl Append for CtString { + fn empty() -> Self { + "".as_ctstring() + } + + fn append(self, other: Self) -> Self { + f"{self}{other}".as_ctstring() + } +} + +// docs:start:as-ctstring +pub trait AsCtString { + comptime fn as_ctstring(self) -> CtString; +} +// docs:end:as-ctstring + +impl AsCtString for str { + comptime fn as_ctstring(self) -> CtString { + str_as_ctstring(self) + } +} + +impl AsCtString for fmtstr { + comptime fn as_ctstring(self) -> CtString { + fmtstr_as_ctstring(self) + } +} + +impl crate::cmp::Eq for CtString { + comptime fn eq(self, other: Self) -> bool { + ctstring_eq(self, other) + } +} + +impl crate::hash::Hash for CtString { + comptime fn hash(self, state: &mut H) + where + H: crate::hash::Hasher, + { + state.write(ctstring_hash(self)); + } +} + +#[builtin(str_as_ctstring)] +comptime fn str_as_ctstring(_s: str) -> CtString {} + +#[builtin(fmtstr_as_ctstring)] +comptime fn fmtstr_as_ctstring(_s: fmtstr) -> CtString {} + +#[builtin(ctstring_eq)] +comptime fn ctstring_eq(_first: CtString, _second: CtString) -> bool {} + +#[builtin(ctstring_hash)] +comptime fn ctstring_hash(_string: CtString) -> Field {} + +mod test { + use super::AsCtString; + + #[test] + fn as_quoted_str_example() { + comptime { + // docs:start:as_quoted_str_example + let my_ctstring = "foo bar".as_ctstring(); + let my_str = my_ctstring.as_quoted_str!(); + + assert_eq(crate::meta::type_of(my_str), quote { str<7> }.as_type()); + // docs:end:as_quoted_str_example + } + } +} diff --git a/noir_stdlib/src/meta/expr.nr b/noir_stdlib/src/meta/expr.nr new file mode 100644 index 00000000000..7538b26dc44 --- /dev/null +++ b/noir_stdlib/src/meta/expr.nr @@ -0,0 +1,682 @@ +//! Contains methods on the built-in `Expr` type for quoted, syntactically valid expressions. + +use crate::meta::op::BinaryOp; +use crate::meta::op::UnaryOp; +use crate::option::Option; + +impl Expr { + /// If this expression is an array literal `[elem1, ..., elemN]`, this returns a slice of each element in the array. + #[builtin(expr_as_array)] + // docs:start:as_array + pub comptime fn as_array(self) -> Option<[Expr]> {} + // docs:end:as_array + + /// If this expression is an assert, this returns the assert expression and the optional message. + #[builtin(expr_as_assert)] + // docs:start:as_assert + pub comptime fn as_assert(self) -> Option<(Expr, Option)> {} + // docs:end:as_assert + + /// If this expression is an assert_eq, this returns the left-hand-side and right-hand-side + /// expressions, together with the optional message. + #[builtin(expr_as_assert_eq)] + // docs:start:as_assert_eq + pub comptime fn as_assert_eq(self) -> Option<(Expr, Expr, Option)> {} + // docs:end:as_assert_eq + + /// If this expression is an assignment, this returns a tuple with the left hand side + /// and right hand side in order. + #[builtin(expr_as_assign)] + // docs:start:as_assign + pub comptime fn as_assign(self) -> Option<(Expr, Expr)> {} + // docs:end:as_assign + + /// If this expression is a binary operator operation ` `, + /// return the left-hand side, operator, and the right-hand side of the operation. + #[builtin(expr_as_binary_op)] + // docs:start:as_binary_op + pub comptime fn as_binary_op(self) -> Option<(Expr, BinaryOp, Expr)> {} + // docs:end:as_binary_op + + /// If this expression is a block `{ stmt1; stmt2; ...; stmtN }`, return + /// a slice containing each statement. + #[builtin(expr_as_block)] + // docs:start:as_block + pub comptime fn as_block(self) -> Option<[Expr]> {} + // docs:end:as_block + + /// If this expression is a boolean literal, return that literal. + #[builtin(expr_as_bool)] + // docs:start:as_bool + pub comptime fn as_bool(self) -> Option {} + // docs:end:as_bool + + /// If this expression is a cast expression `expr as type`, returns the casted + /// expression and the type to cast to. + // docs:start:as_cast + #[builtin(expr_as_cast)] + pub comptime fn as_cast(self) -> Option<(Expr, UnresolvedType)> {} + // docs:end:as_cast + + /// If this expression is a `comptime { stmt1; stmt2; ...; stmtN }` block, + /// return each statement in the block. + #[builtin(expr_as_comptime)] + // docs:start:as_comptime + pub comptime fn as_comptime(self) -> Option<[Expr]> {} + // docs:end:as_comptime + + /// If this expression is a constructor `Type { field1: expr1, ..., fieldN: exprN }`, + /// return the type and the fields. + #[builtin(expr_as_constructor)] + // docs:start:as_constructor + pub comptime fn as_constructor(self) -> Option<(UnresolvedType, [(Quoted, Expr)])> {} + // docs:end:as_constructor + + /// If this expression is a for statement over a single expression, return the identifier, + /// the expression and the for loop body. + #[builtin(expr_as_for)] + // docs:start:as_for + pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} + // docs:end:as_for + + /// If this expression is a for statement over a range, return the identifier, + /// the range start, the range end and the for loop body. + #[builtin(expr_as_for_range)] + // docs:start:as_for_range + pub comptime fn as_for_range(self) -> Option<(Quoted, Expr, Expr, Expr)> {} + // docs:end:as_for_range + + /// If this expression is a function call `foo(arg1, ..., argN)`, return + /// the function and a slice of each argument. + #[builtin(expr_as_function_call)] + // docs:start:as_function_call + pub comptime fn as_function_call(self) -> Option<(Expr, [Expr])> {} + // docs:end:as_function_call + + /// If this expression is an `if condition { then_branch } else { else_branch }`, + /// return the condition, then branch, and else branch. If there is no else branch, + /// `None` is returned for that branch instead. + #[builtin(expr_as_if)] + // docs:start:as_if + pub comptime fn as_if(self) -> Option<(Expr, Expr, Option)> {} + // docs:end:as_if + + /// If this expression is an index into an array `array[index]`, return the + /// array and the index. + #[builtin(expr_as_index)] + // docs:start:as_index + pub comptime fn as_index(self) -> Option<(Expr, Expr)> {} + // docs:end:as_index + + /// If this expression is an integer literal, return the integer as a field + /// as well as whether the integer is negative (true) or not (false). + #[builtin(expr_as_integer)] + // docs:start:as_integer + pub comptime fn as_integer(self) -> Option<(Field, bool)> {} + // docs:end:as_integer + + /// If this expression is a lambda, returns the parameters, return type and body. + #[builtin(expr_as_lambda)] + // docs:start:as_lambda + pub comptime fn as_lambda( + self, + ) -> Option<([(Expr, Option)], Option, Expr)> {} + // docs:end:as_lambda + + /// If this expression is a let statement, returns the let pattern as an `Expr`, + /// the optional type annotation, and the assigned expression. + #[builtin(expr_as_let)] + // docs:start:as_let + pub comptime fn as_let(self) -> Option<(Expr, Option, Expr)> {} + // docs:end:as_let + + /// If this expression is a member access `foo.bar`, return the struct/tuple + /// expression and the field. The field will be represented as a quoted value. + #[builtin(expr_as_member_access)] + // docs:start:as_member_access + pub comptime fn as_member_access(self) -> Option<(Expr, Quoted)> {} + // docs:end:as_member_access + + /// If this expression is a method call `foo.bar::(arg1, ..., argN)`, return + /// the receiver, method name, a slice of each generic argument, and a slice of each argument. + #[builtin(expr_as_method_call)] + // docs:start:as_method_call + pub comptime fn as_method_call(self) -> Option<(Expr, Quoted, [UnresolvedType], [Expr])> {} + // docs:end:as_method_call + + /// If this expression is a repeated element array `[elem; length]`, return + /// the repeated element and the length expressions. + #[builtin(expr_as_repeated_element_array)] + // docs:start:as_repeated_element_array + pub comptime fn as_repeated_element_array(self) -> Option<(Expr, Expr)> {} + // docs:end:as_repeated_element_array + + /// If this expression is a repeated element slice `[elem; length]`, return + /// the repeated element and the length expressions. + #[builtin(expr_as_repeated_element_slice)] + // docs:start:as_repeated_element_slice + pub comptime fn as_repeated_element_slice(self) -> Option<(Expr, Expr)> {} + // docs:end:as_repeated_element_slice + + /// If this expression is a slice literal `&[elem1, ..., elemN]`, + /// return each element of the slice. + #[builtin(expr_as_slice)] + // docs:start:as_slice + pub comptime fn as_slice(self) -> Option<[Expr]> {} + // docs:end:as_slice + + /// If this expression is a tuple `(field1, ..., fieldN)`, + /// return each element of the tuple. + #[builtin(expr_as_tuple)] + // docs:start:as_tuple + pub comptime fn as_tuple(self) -> Option<[Expr]> {} + // docs:end:as_tuple + + /// If this expression is a unary operation ` `, + /// return the unary operator as well as the right-hand side expression. + #[builtin(expr_as_unary_op)] + // docs:start:as_unary_op + pub comptime fn as_unary_op(self) -> Option<(UnaryOp, Expr)> {} + // docs:end:as_unary_op + + /// If this expression is an `unsafe { stmt1; ...; stmtN }` block, + /// return each statement inside in a slice. + #[builtin(expr_as_unsafe)] + // docs:start:as_unsafe + pub comptime fn as_unsafe(self) -> Option<[Expr]> {} + // docs:end:as_unsafe + + /// Returns `true` if this expression is trailed by a semicolon. + /// + /// Example: + /// + /// ```noir + /// comptime { + /// let expr1 = quote { 1 + 2 }.as_expr().unwrap(); + /// let expr2 = quote { 1 + 2; }.as_expr().unwrap(); + /// + /// assert(expr1.as_binary_op().is_some()); + /// assert(expr2.as_binary_op().is_some()); + /// + /// assert(!expr1.has_semicolon()); + /// assert(expr2.has_semicolon()); + /// } + /// ``` + #[builtin(expr_has_semicolon)] + // docs:start:has_semicolon + pub comptime fn has_semicolon(self) -> bool {} + // docs:end:has_semicolon + + /// Returns `true` if this expression is `break`. + #[builtin(expr_is_break)] + // docs:start:is_break + pub comptime fn is_break(self) -> bool {} + // docs:end:is_break + + /// Returns `true` if this expression is `continue`. + #[builtin(expr_is_continue)] + // docs:start:is_continue + pub comptime fn is_continue(self) -> bool {} + // docs:end:is_continue + + /// Applies a mapping function to this expression and to all of its sub-expressions. + /// `f` will be applied to each sub-expression first, then applied to the expression itself. + /// + /// This happens recursively for every expression within `self`. + /// + /// For example, calling `modify` on `(&[1], &[2, 3])` with an `f` that returns `Option::some` + /// for expressions that are integers, doubling them, would return `(&[2], &[4, 6])`. + // docs:start:modify + pub comptime fn modify(self, f: fn[Env](Expr) -> Option) -> Expr { + // docs:end:modify + let result = modify_array(self, f); + let result = result.or_else(|| modify_assert(self, f)); + let result = result.or_else(|| modify_assert_eq(self, f)); + let result = result.or_else(|| modify_assign(self, f)); + let result = result.or_else(|| modify_binary_op(self, f)); + let result = result.or_else(|| modify_block(self, f)); + let result = result.or_else(|| modify_cast(self, f)); + let result = result.or_else(|| modify_comptime(self, f)); + let result = result.or_else(|| modify_constructor(self, f)); + let result = result.or_else(|| modify_if(self, f)); + let result = result.or_else(|| modify_index(self, f)); + let result = result.or_else(|| modify_for(self, f)); + let result = result.or_else(|| modify_for_range(self, f)); + let result = result.or_else(|| modify_lambda(self, f)); + let result = result.or_else(|| modify_let(self, f)); + let result = result.or_else(|| modify_function_call(self, f)); + let result = result.or_else(|| modify_member_access(self, f)); + let result = result.or_else(|| modify_method_call(self, f)); + let result = result.or_else(|| modify_repeated_element_array(self, f)); + let result = result.or_else(|| modify_repeated_element_slice(self, f)); + let result = result.or_else(|| modify_slice(self, f)); + let result = result.or_else(|| modify_tuple(self, f)); + let result = result.or_else(|| modify_unary_op(self, f)); + let result = result.or_else(|| modify_unsafe(self, f)); + if result.is_some() { + let result = result.unwrap_unchecked(); + let modified = f(result); + modified.unwrap_or(result) + } else { + f(self).unwrap_or(self) + } + } + + /// Returns this expression as a `Quoted` value. It's the same as `quote { $self }`. + // docs:start:quoted + pub comptime fn quoted(self) -> Quoted { + // docs:end:quoted + quote { $self } + } + + /// Resolves and type-checks this expression and returns the result as a `TypedExpr`. + /// + /// The `in_function` argument specifies where the expression is resolved: + /// - If it's `none`, the expression is resolved in the function where `resolve` was called + /// - If it's `some`, the expression is resolved in the given function + /// + /// If any names used by this expression are not in scope or if there are any type errors, + /// this will give compiler errors as if the expression was written directly into + /// the current `comptime` function. + #[builtin(expr_resolve)] + // docs:start:resolve + pub comptime fn resolve(self, in_function: Option) -> TypedExpr {} + // docs:end:resolve +} + +comptime fn modify_array(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_array().map(|exprs: [Expr]| { + let exprs = modify_expressions(exprs, f); + new_array(exprs) + }) +} + +comptime fn modify_assert(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_assert().map(|expr: (Expr, Option)| { + let (predicate, msg) = expr; + let predicate = predicate.modify(f); + let msg = msg.map(|msg: Expr| msg.modify(f)); + new_assert(predicate, msg) + }) +} + +comptime fn modify_assert_eq(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_assert_eq().map(|expr: (Expr, Expr, Option)| { + let (lhs, rhs, msg) = expr; + let lhs = lhs.modify(f); + let rhs = rhs.modify(f); + let msg = msg.map(|msg: Expr| msg.modify(f)); + new_assert_eq(lhs, rhs, msg) + }) +} + +comptime fn modify_assign(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_assign().map(|expr: (Expr, Expr)| { + let (lhs, rhs) = expr; + let lhs = lhs.modify(f); + let rhs = rhs.modify(f); + new_assign(lhs, rhs) + }) +} + +comptime fn modify_binary_op(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_binary_op().map(|expr: (Expr, BinaryOp, Expr)| { + let (lhs, op, rhs) = expr; + let lhs = lhs.modify(f); + let rhs = rhs.modify(f); + new_binary_op(lhs, op, rhs) + }) +} + +comptime fn modify_block(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_block().map(|exprs: [Expr]| { + let exprs = modify_expressions(exprs, f); + new_block(exprs) + }) +} + +comptime fn modify_cast(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_cast().map(|expr: (Expr, UnresolvedType)| { + let (expr, typ) = expr; + let expr = expr.modify(f); + new_cast(expr, typ) + }) +} + +comptime fn modify_comptime(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_comptime().map(|exprs: [Expr]| { + let exprs = exprs.map(|expr: Expr| expr.modify(f)); + new_comptime(exprs) + }) +} + +comptime fn modify_constructor(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_constructor().map(|expr: (UnresolvedType, [(Quoted, Expr)])| { + let (typ, fields) = expr; + let fields = fields.map(|field: (Quoted, Expr)| { + let (name, value) = field; + (name, value.modify(f)) + }); + new_constructor(typ, fields) + }) +} + +comptime fn modify_function_call( + expr: Expr, + f: fn[Env](Expr) -> Option, +) -> Option { + expr.as_function_call().map(|expr: (Expr, [Expr])| { + let (function, arguments) = expr; + let function = function.modify(f); + let arguments = arguments.map(|arg: Expr| arg.modify(f)); + new_function_call(function, arguments) + }) +} + +comptime fn modify_if(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_if().map(|expr: (Expr, Expr, Option)| { + let (condition, consequence, alternative) = expr; + let condition = condition.modify(f); + let consequence = consequence.modify(f); + let alternative = alternative.map(|alternative: Expr| alternative.modify(f)); + new_if(condition, consequence, alternative) + }) +} + +comptime fn modify_index(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_index().map(|expr: (Expr, Expr)| { + let (object, index) = expr; + let object = object.modify(f); + let index = index.modify(f); + new_index(object, index) + }) +} + +comptime fn modify_for(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_for().map(|expr: (Quoted, Expr, Expr)| { + let (identifier, array, body) = expr; + let array = array.modify(f); + let body = body.modify(f); + new_for(identifier, array, body) + }) +} + +comptime fn modify_for_range(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_for_range().map(|expr: (Quoted, Expr, Expr, Expr)| { + let (identifier, from, to, body) = expr; + let from = from.modify(f); + let to = to.modify(f); + let body = body.modify(f); + new_for_range(identifier, from, to, body) + }) +} + +comptime fn modify_lambda(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_lambda().map(|expr: ([(Expr, Option)], Option, Expr)| { + let (params, return_type, body) = expr; + let params = + params.map(|param: (Expr, Option)| (param.0.modify(f), param.1)); + let body = body.modify(f); + new_lambda(params, return_type, body) + }) +} + +comptime fn modify_let(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_let().map(|expr: (Expr, Option, Expr)| { + let (pattern, typ, expr) = expr; + let pattern = pattern.modify(f); + let expr = expr.modify(f); + new_let(pattern, typ, expr) + }) +} + +comptime fn modify_member_access( + expr: Expr, + f: fn[Env](Expr) -> Option, +) -> Option { + expr.as_member_access().map(|expr: (Expr, Quoted)| { + let (object, name) = expr; + let object = object.modify(f); + new_member_access(object, name) + }) +} + +comptime fn modify_method_call(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_method_call().map(|expr: (Expr, Quoted, [UnresolvedType], [Expr])| { + let (object, name, generics, arguments) = expr; + let object = object.modify(f); + let arguments = arguments.map(|arg: Expr| arg.modify(f)); + new_method_call(object, name, generics, arguments) + }) +} + +comptime fn modify_repeated_element_array( + expr: Expr, + f: fn[Env](Expr) -> Option, +) -> Option { + expr.as_repeated_element_array().map(|expr: (Expr, Expr)| { + let (expr, length) = expr; + let expr = expr.modify(f); + let length = length.modify(f); + new_repeated_element_array(expr, length) + }) +} + +comptime fn modify_repeated_element_slice( + expr: Expr, + f: fn[Env](Expr) -> Option, +) -> Option { + expr.as_repeated_element_slice().map(|expr: (Expr, Expr)| { + let (expr, length) = expr; + let expr = expr.modify(f); + let length = length.modify(f); + new_repeated_element_slice(expr, length) + }) +} + +comptime fn modify_slice(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_slice().map(|exprs: [Expr]| { + let exprs = modify_expressions(exprs, f); + new_slice(exprs) + }) +} + +comptime fn modify_tuple(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_tuple().map(|exprs: [Expr]| { + let exprs = modify_expressions(exprs, f); + new_tuple(exprs) + }) +} + +comptime fn modify_unary_op(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_unary_op().map(|expr: (UnaryOp, Expr)| { + let (op, rhs) = expr; + let rhs = rhs.modify(f); + new_unary_op(op, rhs) + }) +} + +comptime fn modify_unsafe(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_unsafe().map(|exprs: [Expr]| { + let exprs = exprs.map(|expr: Expr| expr.modify(f)); + new_unsafe(exprs) + }) +} + +comptime fn modify_expressions(exprs: [Expr], f: fn[Env](Expr) -> Option) -> [Expr] { + exprs.map(|expr: Expr| expr.modify(f)) +} + +comptime fn new_array(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { , }); + quote { [$exprs]}.as_expr().unwrap() +} + +comptime fn new_assert(predicate: Expr, msg: Option) -> Expr { + if msg.is_some() { + let msg = msg.unwrap(); + quote { assert($predicate, $msg) }.as_expr().unwrap() + } else { + quote { assert($predicate) }.as_expr().unwrap() + } +} + +comptime fn new_assert_eq(lhs: Expr, rhs: Expr, msg: Option) -> Expr { + if msg.is_some() { + let msg = msg.unwrap(); + quote { assert_eq($lhs, $rhs, $msg) }.as_expr().unwrap() + } else { + quote { assert_eq($lhs, $rhs) }.as_expr().unwrap() + } +} + +comptime fn new_assign(lhs: Expr, rhs: Expr) -> Expr { + quote { $lhs = $rhs }.as_expr().unwrap() +} + +comptime fn new_binary_op(lhs: Expr, op: BinaryOp, rhs: Expr) -> Expr { + let op = op.quoted(); + quote { ($lhs) $op ($rhs) }.as_expr().unwrap() +} + +comptime fn new_block(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { ; }); + quote { { $exprs }}.as_expr().unwrap() +} + +comptime fn new_cast(expr: Expr, typ: UnresolvedType) -> Expr { + quote { ($expr) as $typ }.as_expr().unwrap() +} + +comptime fn new_comptime(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { ; }); + quote { comptime { $exprs }}.as_expr().unwrap() +} + +comptime fn new_constructor(typ: UnresolvedType, fields: [(Quoted, Expr)]) -> Expr { + let fields = fields + .map(|field: (Quoted, Expr)| { + let (name, value) = field; + quote { $name: $value } + }) + .join(quote { , }); + quote { $typ { $fields }}.as_expr().unwrap() +} + +comptime fn new_if(condition: Expr, consequence: Expr, alternative: Option) -> Expr { + if alternative.is_some() { + let alternative = alternative.unwrap(); + quote { if $condition { $consequence } else { $alternative }}.as_expr().unwrap() + } else { + quote { if $condition { $consequence } }.as_expr().unwrap() + } +} + +comptime fn new_for(identifier: Quoted, array: Expr, body: Expr) -> Expr { + quote { for $identifier in $array { $body } }.as_expr().unwrap() +} + +comptime fn new_for_range(identifier: Quoted, from: Expr, to: Expr, body: Expr) -> Expr { + quote { for $identifier in $from .. $to { $body } }.as_expr().unwrap() +} + +comptime fn new_index(object: Expr, index: Expr) -> Expr { + quote { $object[$index] }.as_expr().unwrap() +} + +comptime fn new_lambda( + params: [(Expr, Option)], + return_type: Option, + body: Expr, +) -> Expr { + let params = params + .map(|param: (Expr, Option)| { + let (name, typ) = param; + if typ.is_some() { + let typ = typ.unwrap(); + quote { $name: $typ } + } else { + quote { $name } + } + }) + .join(quote { , }); + + if return_type.is_some() { + let return_type = return_type.unwrap(); + quote { |$params| -> $return_type { $body } }.as_expr().unwrap() + } else { + quote { |$params| { $body } }.as_expr().unwrap() + } +} + +comptime fn new_let(pattern: Expr, typ: Option, expr: Expr) -> Expr { + if typ.is_some() { + let typ = typ.unwrap(); + quote { let $pattern : $typ = $expr; }.as_expr().unwrap() + } else { + quote { let $pattern = $expr; }.as_expr().unwrap() + } +} + +comptime fn new_member_access(object: Expr, name: Quoted) -> Expr { + quote { $object.$name }.as_expr().unwrap() +} + +comptime fn new_function_call(function: Expr, arguments: [Expr]) -> Expr { + let arguments = join_expressions(arguments, quote { , }); + + quote { $function($arguments) }.as_expr().unwrap() +} + +comptime fn new_method_call( + object: Expr, + name: Quoted, + generics: [UnresolvedType], + arguments: [Expr], +) -> Expr { + let arguments = join_expressions(arguments, quote { , }); + + if generics.len() == 0 { + quote { $object.$name($arguments) }.as_expr().unwrap() + } else { + let generics = generics.map(|generic| quote { $generic }).join(quote { , }); + quote { $object.$name::<$generics>($arguments) }.as_expr().unwrap() + } +} + +comptime fn new_repeated_element_array(expr: Expr, length: Expr) -> Expr { + quote { [$expr; $length] }.as_expr().unwrap() +} + +comptime fn new_repeated_element_slice(expr: Expr, length: Expr) -> Expr { + quote { &[$expr; $length] }.as_expr().unwrap() +} + +comptime fn new_slice(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { , }); + quote { &[$exprs]}.as_expr().unwrap() +} + +comptime fn new_tuple(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { , }); + quote { ($exprs) }.as_expr().unwrap() +} + +comptime fn new_unary_op(op: UnaryOp, rhs: Expr) -> Expr { + let op = op.quoted(); + quote { $op($rhs) }.as_expr().unwrap() +} + +comptime fn new_unsafe(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { ; }); + quote { + /// Safety: generated by macro + unsafe { $exprs } + } + .as_expr() + .unwrap() +} + +comptime fn join_expressions(exprs: [Expr], separator: Quoted) -> Quoted { + exprs.map(|expr: Expr| expr.quoted()).join(separator) +} diff --git a/noir_stdlib/src/meta/format_string.nr b/noir_stdlib/src/meta/format_string.nr new file mode 100644 index 00000000000..5e639dc278e --- /dev/null +++ b/noir_stdlib/src/meta/format_string.nr @@ -0,0 +1,6 @@ +impl fmtstr { + #[builtin(fmtstr_quoted_contents)] + // docs:start:quoted_contents + pub comptime fn quoted_contents(self) -> Quoted {} + // docs:end:quoted_contents +} diff --git a/noir_stdlib/src/meta/function_def.nr b/noir_stdlib/src/meta/function_def.nr new file mode 100644 index 00000000000..010110d678e --- /dev/null +++ b/noir_stdlib/src/meta/function_def.nr @@ -0,0 +1,90 @@ +impl FunctionDefinition { + #[builtin(function_def_add_attribute)] + // docs:start:add_attribute + pub comptime fn add_attribute(self, attribute: str) {} + // docs:end:add_attribute + + #[builtin(function_def_body)] + // docs:start:body + pub comptime fn body(self) -> Expr {} + // docs:end:body + + #[builtin(function_def_has_named_attribute)] + // docs:start:has_named_attribute + pub comptime fn has_named_attribute(self, name: str) -> bool {} + // docs:end:has_named_attribute + + #[builtin(function_def_is_unconstrained)] + // docs:start:is_unconstrained + pub comptime fn is_unconstrained(self) -> bool {} + // docs:end:is_unconstrained + + #[builtin(function_def_module)] + // docs:start:module + pub comptime fn module(self) -> Module {} + // docs:end:module + + #[builtin(function_def_name)] + // docs:start:name + pub comptime fn name(self) -> Quoted {} + // docs:end:name + + #[builtin(function_def_parameters)] + // docs:start:parameters + pub comptime fn parameters(self) -> [(Quoted, Type)] {} + // docs:end:parameters + + #[builtin(function_def_return_type)] + // docs:start:return_type + pub comptime fn return_type(self) -> Type {} + // docs:end:return_type + + #[builtin(function_def_set_body)] + // docs:start:set_body + pub comptime fn set_body(self, body: Expr) {} + // docs:end:set_body + + #[builtin(function_def_set_parameters)] + // docs:start:set_parameters + pub comptime fn set_parameters(self, parameters: [(Quoted, Type)]) {} + // docs:end:set_parameters + + #[builtin(function_def_set_return_type)] + // docs:start:set_return_type + pub comptime fn set_return_type(self, return_type: Type) {} + // docs:end:set_return_type + + #[builtin(function_def_set_return_public)] + // docs:start:set_return_public + pub comptime fn set_return_public(self, public: bool) {} + // docs:end:set_return_public + + #[builtin(function_def_set_return_data)] + comptime fn set_return_data(self) {} + + #[builtin(function_def_set_unconstrained)] + // docs:start:set_unconstrained + pub comptime fn set_unconstrained(self, value: bool) {} + // docs:end:set_unconstrained +} + +impl crate::hash::Hash for FunctionDefinition { + comptime fn hash(self, state: &mut H) + where + H: crate::hash::Hasher, + { + state.write(function_def_hash(self)) + } +} + +impl crate::cmp::Eq for FunctionDefinition { + comptime fn eq(self, other: Self) -> bool { + function_def_eq(self, other) + } +} + +#[builtin(function_def_eq)] +comptime fn function_def_eq(_first: FunctionDefinition, _second: FunctionDefinition) -> bool {} + +#[builtin(function_def_hash)] +comptime fn function_def_hash(_function: FunctionDefinition) -> Field {} diff --git a/noir_stdlib/src/meta/mod.nr b/noir_stdlib/src/meta/mod.nr new file mode 100644 index 00000000000..21c1b14cc96 --- /dev/null +++ b/noir_stdlib/src/meta/mod.nr @@ -0,0 +1,304 @@ +pub mod ctstring; +pub mod expr; +pub mod format_string; +pub mod function_def; +pub mod module; +pub mod op; +pub mod struct_def; +pub mod trait_constraint; +pub mod trait_def; +pub mod trait_impl; +pub mod typ; +pub mod typed_expr; +pub mod quoted; +pub mod unresolved_type; + +use crate::default::Default; + +/// Calling unquote as a macro (via `unquote!(arg)`) will unquote +/// its argument. Since this is the effect `!` already does, `unquote` +/// itself does not need to do anything besides return its argument. +// docs:start:unquote +pub comptime fn unquote(code: Quoted) -> Quoted { + // docs:end:unquote + code +} + +/// Returns the type of any value +#[builtin(type_of)] +// docs:start:type_of +pub comptime fn type_of(x: T) -> Type {} +// docs:end:type_of + +// docs:start:derive_example +// These are needed for the unconstrained hashmap we're using to store derive functions +use crate::collections::umap::UHashMap; +use crate::hash::BuildHasherDefault; +use crate::hash::poseidon2::Poseidon2Hasher; + +// A derive function is one that given a struct definition can +// create us a quoted trait impl from it. +pub type DeriveFunction = fn(StructDefinition) -> Quoted; + +// We'll keep a global HANDLERS map to keep track of the derive handler for each trait +comptime mut global HANDLERS: UHashMap> = + UHashMap::default(); + +// Given a struct and a slice of traits to derive, create trait impls for each. +// This function is as simple as iterating over the slice, checking if we have a trait +// handler registered for the given trait, calling it, and appending the result. +// docs:start:derive +#[varargs] +pub comptime fn derive(s: StructDefinition, traits: [TraitDefinition]) -> Quoted { + // docs:end:derive + let mut result = quote {}; + + for trait_to_derive in traits { + let handler = HANDLERS.get(trait_to_derive); + assert(handler.is_some(), f"No derive function registered for `{trait_to_derive}`"); + + let trait_impl = handler.unwrap()(s); + result = quote { $result $trait_impl }; + } + + result +} +// docs:end:derive_example + +// docs:start:derive_via +// To register a handler for a trait, just add it to our handlers map +// docs:start:derive_via_signature +pub comptime fn derive_via(t: TraitDefinition, f: DeriveFunction) { + // docs:end:derive_via_signature + HANDLERS.insert(t, f); +} +// docs:end:derive_via + +/// `make_impl` is a helper function to make a simple impl, usually while deriving a trait. +/// This impl has a couple assumptions: +/// 1. The impl only has one function, with the signature `function_signature` +/// 2. The trait itself does not have any generics. +/// +/// While these assumptions are met, `make_impl` will create an impl from a StructDefinition, +/// automatically filling in the required generics from the struct, along with the where clause. +/// The function body is created by mapping each field with `for_each_field` and joining the +/// results with `join_fields_with`. The result of this is passed to the `body` function for +/// any final processing - e.g. wrapping each field in a `StructConstructor { .. }` expression. +/// +/// See `derive_eq` and `derive_default` for example usage. +// docs:start:make_trait_impl +pub comptime fn make_trait_impl( + s: StructDefinition, + trait_name: Quoted, + function_signature: Quoted, + for_each_field: fn[Env1](Quoted) -> Quoted, + join_fields_with: Quoted, + body: fn[Env2](Quoted) -> Quoted, +) -> Quoted { + // docs:end:make_trait_impl + let typ = s.as_type(); + let impl_generics = s.generics().map(|g| quote { $g }).join(quote {,}); + let where_clause = s.generics().map(|name| quote { $name: $trait_name }).join(quote {,}); + + // `for_each_field(field1) $join_fields_with for_each_field(field2) $join_fields_with ...` + let fields = s.fields_as_written().map(|f: (Quoted, Type)| { + let name = f.0; + for_each_field(name) + }); + let body = body(fields.join(join_fields_with)); + + quote { + impl<$impl_generics> $trait_name for $typ where $where_clause { + $function_signature { + $body + } + } + } +} + +mod tests { + use crate::meta::ctstring::AsCtString; + use crate::meta::derive_via; + + // docs:start:quote-example + comptime fn quote_one() -> Quoted { + quote { 1 } + } + + #[test] + fn returning_versus_macro_insertion() { + comptime { + // let _a: Quoted = quote { 1 }; + let _a: Quoted = quote_one(); + + // let _b: Field = 1; + let _b: Field = quote_one!(); + + // Since integers default to fields, if we + // want a different type we have to explicitly cast + // let _c: i32 = 1 as i32; + let _c: i32 = quote_one!() as i32; + } + } + // docs:end:quote-example + + // docs:start:derive-field-count-example + trait FieldCount { + fn field_count() -> u32; + } + + #[derive_field_count] + struct Bar { + x: Field, + y: [Field; 2], + } + + comptime fn derive_field_count(s: StructDefinition) -> Quoted { + let typ = s.as_type(); + let field_count = s.fields_as_written().len(); + quote { + impl FieldCount for $typ { + fn field_count() -> u32 { + $field_count + } + } + } + } + // docs:end:derive-field-count-example + + // docs:start:annotation-arguments-example + #[assert_field_is_type(quote { i32 }.as_type())] + struct MyStruct { + my_field: i32, + } + + comptime fn assert_field_is_type(s: StructDefinition, typ: Type) { + // Assert the first field in `s` has type `typ` + let fields = s.fields([]); + assert_eq(fields[0].1, typ); + } + // docs:end:annotation-arguments-example + + // docs:start:annotation-varargs-example + #[assert_three_args(1, 2, 3)] + struct MyOtherStruct { + my_other_field: u32, + } + + #[varargs] + comptime fn assert_three_args(_s: StructDefinition, args: [Field]) { + assert_eq(args.len(), 3); + } + // docs:end:annotation-varargs-example + + // docs:start:big-derive-usage-example + // Finally, to register a handler we call the above function as an annotation + // with our handler function. + #[derive_via(derive_do_nothing)] + trait DoNothing { + fn do_nothing(self); + } + + comptime fn derive_do_nothing(s: StructDefinition) -> Quoted { + // This is simplified since we don't handle generics or where clauses! + // In a real example we'd likely also need to introduce each of + // `s.generics()` as well as a trait constraint for each generic + // to ensure they also implement the trait. + let typ = s.as_type(); + quote { + impl DoNothing for $typ { + fn do_nothing(self) { + // Traits can't tell us what to do + println("something"); + } + } + } + } + + // Since `DoNothing` is a simple trait which: + // 1. Only has one method + // 2. Does not have any generics on the trait itself + // We can use `std::meta::make_trait_impl` to help us out. + // This helper function will generate our impl for us along with any + // necessary where clauses and still provides a flexible interface + // for us to work on each field on the struct. + comptime fn derive_do_nothing_alt(s: StructDefinition) -> Quoted { + let trait_name = quote { DoNothing }; + let method_signature = quote { fn do_nothing(self) }; + + // Call `do_nothing` recursively on each field in the struct + let for_each_field = |field_name| quote { self.$field_name.do_nothing(); }; + + // Some traits like Eq want to join each field expression with something like `&`. + // We don't need that here + let join_fields_with = quote {}; + + // The body function is a spot to insert any extra setup/teardown needed. + // We'll insert our println here. Since we recur on each field, we should see + // one println for the struct itself, followed by a println for every field (recursively). + let body = |body| quote { + println("something"); + $body + }; + crate::meta::make_trait_impl( + s, + trait_name, + method_signature, + for_each_field, + join_fields_with, + body, + ) + } + // docs:end:big-derive-usage-example + + impl DoNothing for Bar { + fn do_nothing(_: Self) {} + } + + // docs:start:concatenate-example + comptime fn concatenate(q1: Quoted, q2: Quoted) -> Quoted { + assert(q1.tokens().len() <= 1); + assert(q2.tokens().len() <= 1); + + f"{q1}{q2}".quoted_contents() + } + + // The CtString type is also useful for a compile-time string of unbounded size + // so that you can append to it in a loop. + comptime fn double_spaced(q: Quoted) -> CtString { + let mut result = "".as_ctstring(); + + for token in q.tokens() { + if result != "".as_ctstring() { + result = result.append_str(" "); + } + result = result.append_fmtstr(f"{token}"); + } + + result + } + + #[test] + fn concatenate_test() { + comptime { + let result = concatenate(quote {foo}, quote {bar}); + assert_eq(result, quote {foobar}); + + let result = double_spaced(quote {foo bar 3}).as_quoted_str!(); + assert_eq(result, "foo bar 3"); + } + } + // docs:end:concatenate-example + + // This function is just to remove unused warnings + fn remove_unused_warnings() { + let _: Bar = Bar { x: 1, y: [2, 3] }; + let _: MyStruct = MyStruct { my_field: 1 }; + let _: MyOtherStruct = MyOtherStruct { my_other_field: 2 }; + let _ = derive_do_nothing(crate::panic::panic(f"")); + let _ = derive_do_nothing_alt(crate::panic::panic(f"")); + if false { + remove_unused_warnings(); + } + } +} diff --git a/noir_stdlib/src/meta/module.nr b/noir_stdlib/src/meta/module.nr new file mode 100644 index 00000000000..0298282761a --- /dev/null +++ b/noir_stdlib/src/meta/module.nr @@ -0,0 +1,52 @@ +impl Module { + #[builtin(module_add_item)] + // docs:start:add_item + pub comptime fn add_item(self, item: Quoted) {} + // docs:end:add_item + + #[builtin(module_has_named_attribute)] + // docs:start:has_named_attribute + pub comptime fn has_named_attribute(self, name: str) -> bool {} + // docs:end:has_named_attribute + + #[builtin(module_is_contract)] + // docs:start:is_contract + pub comptime fn is_contract(self) -> bool {} + // docs:end:is_contract + + #[builtin(module_functions)] + // docs:start:functions + pub comptime fn functions(self) -> [FunctionDefinition] {} + // docs:end:functions + + #[builtin(module_structs)] + // docs:start:structs + pub comptime fn structs(self) -> [StructDefinition] {} + // docs:end:structs + + #[builtin(module_name)] + // docs:start:name + pub comptime fn name(self) -> Quoted {} + // docs:end:name +} + +impl crate::hash::Hash for Module { + comptime fn hash(self, state: &mut H) + where + H: crate::hash::Hasher, + { + state.write(module_hash(self)) + } +} + +impl crate::cmp::Eq for Module { + comptime fn eq(self, other: Self) -> bool { + module_eq(self, other) + } +} + +#[builtin(module_eq)] +comptime fn module_eq(_first: Module, _second: Module) -> bool {} + +#[builtin(module_hash)] +comptime fn module_hash(_module: Module) -> Field {} diff --git a/noir_stdlib/src/meta/op.nr b/noir_stdlib/src/meta/op.nr new file mode 100644 index 00000000000..67c9b4cdb64 --- /dev/null +++ b/noir_stdlib/src/meta/op.nr @@ -0,0 +1,225 @@ +use crate::hash::Hash; + +pub struct UnaryOp { + op: Field, +} + +// Cannot derive Eq or Hash since they internally use paths +// starting with std:: which is invalid within the same crate. +// We'd need to use crate:: instead. +impl crate::cmp::Eq for UnaryOp { + fn eq(self, other: Self) -> bool { + self.op == other.op + } +} + +impl crate::hash::Hash for UnaryOp { + fn hash(self, h: &mut H) + where + H: crate::hash::Hasher, + { + self.op.hash(h); + } +} + +impl UnaryOp { + // docs:start:is_minus + pub fn is_minus(self) -> bool { + // docs:end:is_minus + self.op == 0 + } + + // docs:start:is_not + pub fn is_not(self) -> bool { + // docs:end:is_not + self.op == 1 + } + + // docs:start:is_mutable_reference + pub fn is_mutable_reference(self) -> bool { + // docs:end:is_mutable_reference + self.op == 2 + } + + // docs:start:is_dereference + pub fn is_dereference(self) -> bool { + // docs:end:is_dereference + self.op == 3 + } + + // docs:start:unary_quoted + pub comptime fn quoted(self) -> Quoted { + // docs:end:unary_quoted + if self.is_minus() { + quote { - } + } else if self.is_not() { + quote { ! } + } else if self.is_mutable_reference() { + quote { &mut } + } else if self.is_dereference() { + quote { * } + } else { + let op = self; + crate::panic::panic(f"Unexpected unary operator in UnaryOp::quoted: {op}") + } + } +} + +pub struct BinaryOp { + op: Field, +} + +impl crate::cmp::Eq for BinaryOp { + fn eq(self, other: Self) -> bool { + self.op == other.op + } +} + +impl crate::hash::Hash for BinaryOp { + fn hash(self, h: &mut H) + where + H: crate::hash::Hasher, + { + self.op.hash(h); + } +} + +impl BinaryOp { + // docs:start:is_add + pub fn is_add(self) -> bool { + // docs:end:is_add + self.op == 0 + } + + // docs:start:is_subtract + pub fn is_subtract(self) -> bool { + // docs:end:is_subtract + self.op == 1 + } + + // docs:start:is_multiply + pub fn is_multiply(self) -> bool { + // docs:end:is_multiply + self.op == 2 + } + + // docs:start:is_divide + pub fn is_divide(self) -> bool { + // docs:end:is_divide + self.op == 3 + } + + // docs:start:is_equal + pub fn is_equal(self) -> bool { + // docs:end:is_equal + self.op == 4 + } + + // docs:start:is_not_equal + pub fn is_not_equal(self) -> bool { + // docs:end:is_not_equal + self.op == 5 + } + + // docs:start:is_less_than + pub fn is_less_than(self) -> bool { + // docs:end:is_less_than + self.op == 6 + } + + // docs:start:is_less_than_or_equal + pub fn is_less_than_or_equal(self) -> bool { + // docs:end:is_less_than_or_equal + self.op == 7 + } + + // docs:start:is_greater_than + pub fn is_greater_than(self) -> bool { + // docs:end:is_greater_than + self.op == 8 + } + + // docs:start:is_greater_than_or_equal + pub fn is_greater_than_or_equal(self) -> bool { + // docs:end:is_greater_than_or_equal + self.op == 9 + } + + // docs:start:is_and + pub fn is_and(self) -> bool { + // docs:end:is_and + self.op == 10 + } + + // docs:start:is_or + pub fn is_or(self) -> bool { + // docs:end:is_or + self.op == 11 + } + + // docs:start:is_xor + pub fn is_xor(self) -> bool { + // docs:end:is_xor + self.op == 12 + } + + // docs:start:is_shift_right + pub fn is_shift_right(self) -> bool { + // docs:end:is_shift_right + self.op == 13 + } + + // docs:start:is_shift_left + pub fn is_shift_left(self) -> bool { + // docs:end:is_shift_left + self.op == 14 + } + + // docs:start:is_modulo + pub fn is_modulo(self) -> bool { + // docs:end:is_modulo + self.op == 15 + } + + // docs:start:binary_quoted + pub comptime fn quoted(self) -> Quoted { + // docs:end:binary_quoted + if self.is_add() { + quote { + } + } else if self.is_subtract() { + quote { - } + } else if self.is_multiply() { + quote { * } + } else if self.is_divide() { + quote { / } + } else if self.is_equal() { + quote { == } + } else if self.is_not_equal() { + quote { != } + } else if self.is_less_than() { + quote { < } + } else if self.is_less_than_or_equal() { + quote { <= } + } else if self.is_greater_than() { + quote { > } + } else if self.is_greater_than_or_equal() { + quote { >= } + } else if self.is_and() { + quote { & } + } else if self.is_or() { + quote { | } + } else if self.is_xor() { + quote { ^ } + } else if self.is_shift_right() { + quote { >> } + } else if self.is_shift_left() { + quote { << } + } else if self.is_modulo() { + quote { % } + } else { + let op = self; + crate::panic::panic(f"Unexpected binary operator in BinaryOp::quoted: {op}") + } + } +} + diff --git a/noir_stdlib/src/meta/quoted.nr b/noir_stdlib/src/meta/quoted.nr new file mode 100644 index 00000000000..d67174d7829 --- /dev/null +++ b/noir_stdlib/src/meta/quoted.nr @@ -0,0 +1,50 @@ +use crate::cmp::Eq; +use crate::option::Option; + +impl Quoted { + #[builtin(quoted_as_expr)] + // docs:start:as_expr + pub comptime fn as_expr(self) -> Option {} + // docs:end:as_expr + + #[builtin(quoted_as_module)] + // docs:start:as_module + pub comptime fn as_module(self) -> Option {} + // docs:end:as_module + + #[builtin(quoted_as_trait_constraint)] + // docs:start:as_trait_constraint + pub comptime fn as_trait_constraint(self) -> TraitConstraint {} + // docs:end:as_trait_constraint + + #[builtin(quoted_as_type)] + // docs:start:as_type + pub comptime fn as_type(self) -> Type {} + // docs:end:as_type + + #[builtin(quoted_tokens)] + // docs:start:tokens + pub comptime fn tokens(self) -> [Quoted] {} + // docs:end:tokens +} + +impl Eq for Quoted { + comptime fn eq(self, other: Quoted) -> bool { + quoted_eq(self, other) + } +} + +impl crate::hash::Hash for Quoted { + comptime fn hash(self, state: &mut H) + where + H: crate::hash::Hasher, + { + state.write(quoted_hash(self)) + } +} + +#[builtin(quoted_eq)] +comptime fn quoted_eq(_first: Quoted, _second: Quoted) -> bool {} + +#[builtin(quoted_hash)] +comptime fn quoted_hash(_quoted: Quoted) -> Field {} diff --git a/noir_stdlib/src/meta/struct_def.nr b/noir_stdlib/src/meta/struct_def.nr new file mode 100644 index 00000000000..0e64a537f1f --- /dev/null +++ b/noir_stdlib/src/meta/struct_def.nr @@ -0,0 +1,86 @@ +impl StructDefinition { + #[builtin(struct_def_add_attribute)] + // docs:start:add_attribute + pub comptime fn add_attribute(self, attribute: str) {} + // docs:end:add_attribute + + #[builtin(struct_def_add_generic)] + // docs:start:add_generic + pub comptime fn add_generic(self, generic_name: str) -> Type {} + // docs:end:add_generic + + /// Return a syntactic version of this struct definition as a type. + /// For example, `as_type(quote { type Foo { ... } })` would return `Foo` + #[builtin(struct_def_as_type)] + // docs:start:as_type + pub comptime fn as_type(self) -> Type {} + // docs:end:as_type + + #[builtin(struct_def_has_named_attribute)] + // docs:start:has_named_attribute + pub comptime fn has_named_attribute(self, name: str) -> bool {} + // docs:end:has_named_attribute + + /// Return each generic on this struct. + #[builtin(struct_def_generics)] + // docs:start:generics + pub comptime fn generics(self) -> [Type] {} + // docs:end:generics + + /// Returns (name, type) pairs of each field in this struct. + /// Any generic types used in each field type is automatically substituted with the + /// provided generic arguments. + #[builtin(struct_def_fields)] + // docs:start:fields + pub comptime fn fields(self, generic_args: [Type]) -> [(Quoted, Type)] {} + // docs:end:fields + + /// Returns (name, type) pairs of each field in this struct. Each type is as-is + /// with any generic arguments unchanged. Unless the field types are not needed, + /// users should generally prefer to use `StructDefinition::fields` over this + /// function if possible. + #[builtin(struct_def_fields_as_written)] + // docs:start:fields_as_written + pub comptime fn fields_as_written(self) -> [(Quoted, Type)] {} + // docs:end:fields_as_written + + #[builtin(struct_def_module)] + // docs:start:module + pub comptime fn module(self) -> Module {} + // docs:end:module + + #[builtin(struct_def_name)] + // docs:start:name + pub comptime fn name(self) -> Quoted {} + // docs:end:name + + /// Sets the fields of this struct to the given fields list. + /// All existing fields of the struct will be overridden with the given fields. + /// Each element of the fields list corresponds to the name and type of a field. + /// Each name is expected to be a single identifier. + #[builtin(struct_def_set_fields)] + // docs:start:set_fields + pub comptime fn set_fields(self, new_fields: [(Quoted, Type)]) {} + // docs:end:set_fields +} + +impl crate::hash::Hash for StructDefinition { + comptime fn hash(self, state: &mut H) + where + H: crate::hash::Hasher, + { + state.write(struct_def_hash(self)) + } +} + +impl crate::cmp::Eq for StructDefinition { + comptime fn eq(self, other: Self) -> bool { + struct_def_eq(self, other) + } +} + +#[builtin(struct_def_eq)] +comptime fn struct_def_eq(_first: StructDefinition, _second: StructDefinition) -> bool {} + +#[builtin(struct_def_hash)] +comptime fn struct_def_hash(_struct: StructDefinition) -> Field {} diff --git a/noir_stdlib/src/meta/trait_constraint.nr b/noir_stdlib/src/meta/trait_constraint.nr new file mode 100644 index 00000000000..2d9c6639dbd --- /dev/null +++ b/noir_stdlib/src/meta/trait_constraint.nr @@ -0,0 +1,23 @@ +use crate::cmp::Eq; +use crate::hash::{Hash, Hasher}; + +impl Eq for TraitConstraint { + comptime fn eq(self, other: Self) -> bool { + constraint_eq(self, other) + } +} + +impl Hash for TraitConstraint { + comptime fn hash(self, state: &mut H) + where + H: Hasher, + { + state.write(constraint_hash(self)); + } +} + +#[builtin(trait_constraint_eq)] +comptime fn constraint_eq(_first: TraitConstraint, _second: TraitConstraint) -> bool {} + +#[builtin(trait_constraint_hash)] +comptime fn constraint_hash(_constraint: TraitConstraint) -> Field {} diff --git a/noir_stdlib/src/meta/trait_def.nr b/noir_stdlib/src/meta/trait_def.nr new file mode 100644 index 00000000000..75f746337d4 --- /dev/null +++ b/noir_stdlib/src/meta/trait_def.nr @@ -0,0 +1,30 @@ +use crate::cmp::Eq; +use crate::hash::{Hash, Hasher}; + +impl TraitDefinition { + #[builtin(trait_def_as_trait_constraint)] + // docs:start:as_trait_constraint + pub comptime fn as_trait_constraint(_self: Self) -> TraitConstraint {} + // docs:end:as_trait_constraint +} + +impl Eq for TraitDefinition { + comptime fn eq(self, other: Self) -> bool { + trait_def_eq(self, other) + } +} + +impl Hash for TraitDefinition { + comptime fn hash(self, state: &mut H) + where + H: Hasher, + { + state.write(trait_def_hash(self)); + } +} + +#[builtin(trait_def_eq)] +comptime fn trait_def_eq(_first: TraitDefinition, _second: TraitDefinition) -> bool {} + +#[builtin(trait_def_hash)] +comptime fn trait_def_hash(_def: TraitDefinition) -> Field {} diff --git a/noir_stdlib/src/meta/trait_impl.nr b/noir_stdlib/src/meta/trait_impl.nr new file mode 100644 index 00000000000..9db859bf8a0 --- /dev/null +++ b/noir_stdlib/src/meta/trait_impl.nr @@ -0,0 +1,11 @@ +impl TraitImpl { + #[builtin(trait_impl_trait_generic_args)] + // docs:start:trait_generic_args + pub comptime fn trait_generic_args(self) -> [Type] {} + // docs:end:trait_generic_args + + #[builtin(trait_impl_methods)] + // docs:start:methods + pub comptime fn methods(self) -> [FunctionDefinition] {} + // docs:end:methods +} diff --git a/noir_stdlib/src/meta/typ.nr b/noir_stdlib/src/meta/typ.nr new file mode 100644 index 00000000000..8076c692ca5 --- /dev/null +++ b/noir_stdlib/src/meta/typ.nr @@ -0,0 +1,211 @@ +//! Contains methods on the built-in `Type` type used for representing a type in the source program. + +use crate::cmp::Eq; +use crate::option::Option; + +/// Creates and returns an unbound type variable. This is a special kind of type internal +/// to type checking which will type check with any other type. When it is type checked +/// against another type it will also be set to that type. For example, if `a` is a type +/// variable and we have the type equality `(a, i32) = (u8, i32)`, the compiler will set +/// `a` equal to `u8`. +/// +/// Unbound type variables will often be rendered as `_` while printing them. Bound type +/// variables will appear as the type they are bound to. +/// +/// This can be used in conjunction with functions which internally perform type checks +/// such as `Type::implements` or `Type::get_trait_impl` to potentially grab some of the types used. +/// +/// Note that calling `Type::implements` or `Type::get_trait_impl` on a type variable will always +/// fail. +/// +/// Example: +/// +/// ```noir +/// trait Serialize {} +/// +/// impl Serialize<1> for Field {} +/// +/// impl Serialize for [T; N] +/// where T: Serialize {} +/// +/// impl Serialize for (T, U) +/// where T: Serialize, U: Serialize {} +/// +/// fn fresh_variable_example() { +/// let typevar1 = std::meta::typ::fresh_type_variable(); +/// let constraint = quote { Serialize<$typevar1> }.as_trait_constraint(); +/// let field_type = quote { Field }.as_type(); +/// +/// // Search for a trait impl (binding typevar1 to 1 when the impl is found): +/// assert(field_type.implements(constraint)); +/// +/// // typevar1 should be bound to the "1" generic now: +/// assert_eq(typevar1.as_constant().unwrap(), 1); +/// +/// // If we want to do the same with a different type, we need to +/// // create a new type variable now that `typevar1` is bound +/// let typevar2 = std::meta::typ::fresh_type_variable(); +/// let constraint = quote { Serialize<$typevar2> }.as_trait_constraint(); +/// let array_type = quote { [(Field, Field); 5] }.as_type(); +/// assert(array_type.implements(constraint)); +/// +/// // Now typevar2 should be bound to the serialized pair size 2 times the array length 5 +/// assert_eq(typevar2.as_constant().unwrap(), 10); +/// } +/// ``` +#[builtin(fresh_type_variable)] +// docs:start:fresh_type_variable +pub comptime fn fresh_type_variable() -> Type {} +// docs:end:fresh_type_variable + +impl Type { + /// If this type is an array, return a pair of (element type, size type). + /// + /// Example: + /// + /// ```noir + /// comptime { + /// let array_type = quote { [Field; 3] }.as_type(); + /// let (field_type, three_type) = array_type.as_array().unwrap(); + /// + /// assert(field_type.is_field()); + /// assert_eq(three_type.as_constant().unwrap(), 3); + /// } + /// ``` + #[builtin(type_as_array)] + // docs:start:as_array + pub comptime fn as_array(self) -> Option<(Type, Type)> {} + // docs:end:as_array + + /// If this type is a constant integer (such as the `3` in the array type `[Field; 3]`), + /// return the numeric constant. + #[builtin(type_as_constant)] + // docs:start:as_constant + pub comptime fn as_constant(self) -> Option {} + // docs:end:as_constant + + /// If this is an integer type, return a boolean which is `true` + /// if the type is signed, as well as the number of bits of this integer type. + #[builtin(type_as_integer)] + // docs:start:as_integer + pub comptime fn as_integer(self) -> Option<(bool, u8)> {} + // docs:end:as_integer + + /// If this is a mutable reference type `&mut T`, returns the mutable type `T`. + #[builtin(type_as_mutable_reference)] + // docs:start:as_mutable_reference + comptime fn as_mutable_reference(self) -> Option {} + // docs:end:as_mutable_reference + + /// If this is a slice type, return the element type of the slice. + #[builtin(type_as_slice)] + // docs:start:as_slice + pub comptime fn as_slice(self) -> Option {} + // docs:end:as_slice + + /// If this is a `str` type, returns the length `N` as a type. + #[builtin(type_as_str)] + // docs:start:as_str + pub comptime fn as_str(self) -> Option {} + // docs:end:as_str + + /// If this is a struct type, returns the struct in addition to any generic arguments on this type. + #[builtin(type_as_struct)] + // docs:start:as_struct + pub comptime fn as_struct(self) -> Option<(StructDefinition, [Type])> {} + // docs:end:as_struct + + /// If this is a tuple type, returns each element type of the tuple. + #[builtin(type_as_tuple)] + // docs:start:as_tuple + pub comptime fn as_tuple(self) -> Option<[Type]> {} + // docs:end:as_tuple + + /// Retrieves the trait implementation that implements the given + /// trait constraint for this type. If the trait constraint is not + /// found, `None` is returned. Note that since the concrete trait implementation + /// for a trait constraint specified from a `where` clause is unknown, + /// this function will return `None` in these cases. If you only want to know + /// whether a type implements a trait, use `implements` instead. + /// + /// Example: + /// + /// ```rust + /// comptime { + /// let field_type = quote { Field }.as_type(); + /// let default = quote { Default }.as_trait_constraint(); + /// + /// let the_impl: TraitImpl = field_type.get_trait_impl(default).unwrap(); + /// assert(the_impl.methods().len(), 1); + /// } + /// ``` + #[builtin(type_get_trait_impl)] + // docs:start:get_trait_impl + pub comptime fn get_trait_impl(self, constraint: TraitConstraint) -> Option {} + // docs:end:get_trait_impl + + /// Returns `true` if this type implements the given trait. Note that unlike + /// `get_trait_impl` this will also return true for any `where` constraints + /// in scope. + /// + /// Example: + /// + /// ```rust + /// fn foo() where T: Default { + /// comptime { + /// let field_type = quote { Field }.as_type(); + /// let default = quote { Default }.as_trait_constraint(); + /// assert(field_type.implements(default)); + /// + /// let t = quote { T }.as_type(); + /// assert(t.implements(default)); + /// } + /// } + /// ``` + #[builtin(type_implements)] + // docs:start:implements + pub comptime fn implements(self, constraint: TraitConstraint) -> bool {} + // docs:end:implements + + /// Returns `true` if this type is `bool`. + #[builtin(type_is_bool)] + // docs:start:is_bool + pub comptime fn is_bool(self) -> bool {} + // docs:end:is_bool + + /// Returns `true` if this type is `Field`. + #[builtin(type_is_field)] + // docs:start:is_field + pub comptime fn is_field(self) -> bool {} + // docs:end:is_field + + /// Returns `true` if this type is the unit `()` type. + #[builtin(type_is_unit)] + // docs:start:is_unit + comptime fn is_unit(self) -> bool {} + // docs:end:is_unit +} + +impl Eq for Type { + /// Note that this is syntactic equality, this is not the same as whether two types will type check + /// to be the same type. Unless type inference or generics are being used however, users should not + /// typically have to worry about this distinction. + comptime fn eq(self, other: Self) -> bool { + type_eq(self, other) + } +} + +impl crate::hash::Hash for Type { + comptime fn hash(self, state: &mut H) + where + H: crate::hash::Hasher, + { + state.write(type_hash(self)) + } +} + +#[builtin(type_eq)] +comptime fn type_eq(_first: Type, _second: Type) -> bool {} + +#[builtin(type_hash)] +comptime fn type_hash(_typ: Type) -> Field {} diff --git a/noir_stdlib/src/meta/typed_expr.nr b/noir_stdlib/src/meta/typed_expr.nr new file mode 100644 index 00000000000..c69139ea233 --- /dev/null +++ b/noir_stdlib/src/meta/typed_expr.nr @@ -0,0 +1,16 @@ +//! Contains methods on the built-in `TypedExpr` type for resolved and type-checked expressions. +use crate::option::Option; + +impl TypedExpr { + /// If this expression refers to a function definitions, returns it. Otherwise returns `Option::none()`. + #[builtin(typed_expr_as_function_definition)] + // docs:start:as_function_definition + pub comptime fn as_function_definition(self) -> Option {} + // docs:end:as_function_definition + + /// Returns the type of the expression, if the expression could be resolved without errors. + #[builtin(typed_expr_get_type)] + // docs:start:get_type + pub comptime fn get_type(self) -> Option {} + // docs:end:get_type +} diff --git a/noir_stdlib/src/meta/unresolved_type.nr b/noir_stdlib/src/meta/unresolved_type.nr new file mode 100644 index 00000000000..5c2e8803674 --- /dev/null +++ b/noir_stdlib/src/meta/unresolved_type.nr @@ -0,0 +1,35 @@ +//! Contains methods on the built-in `UnresolvedType` type for the syntax of types. + +use crate::option::Option; + +impl UnresolvedType { + /// If this is a mutable reference type `&mut T`, returns the mutable type `T`. + #[builtin(unresolved_type_as_mutable_reference)] + // docs:start:as_mutable_reference + comptime fn as_mutable_reference(self) -> Option {} + // docs:end:as_mutable_reference + + /// If this is a slice `&[T]`, returns the element type `T`. + #[builtin(unresolved_type_as_slice)] + // docs:start:as_slice + comptime fn as_slice(self) -> Option {} + // docs:end:as_slice + + /// Returns `true` if this type is `bool`. + #[builtin(unresolved_type_is_bool)] + // docs:start:is_bool + comptime fn is_bool(self) -> bool {} + // docs:end:is_bool + + /// Returns true if this type refers to the `Field` type. + #[builtin(unresolved_type_is_field)] + // docs:start:is_field + pub comptime fn is_field(self) -> bool {} + // docs:end:is_field + + /// Returns true if this type is the unit `()` type. + #[builtin(unresolved_type_is_unit)] + // docs:start:is_unit + comptime fn is_unit(self) -> bool {} + // docs:end:is_unit +} diff --git a/noir_stdlib/src/ops/arith.nr b/noir_stdlib/src/ops/arith.nr new file mode 100644 index 00000000000..195ae777580 --- /dev/null +++ b/noir_stdlib/src/ops/arith.nr @@ -0,0 +1,324 @@ +// docs:start:add-trait +pub 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 u1 { + fn add(self, other: u1) -> u1 { + 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 +pub 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 u1 { + fn sub(self, other: u1) -> u1 { + 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 +pub 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 u1 { + fn mul(self, other: u1) -> u1 { + 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 +pub 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 u1 { + fn div(self, other: u1) -> u1 { + 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 +pub 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 u1 { + fn rem(self, other: u1) -> u1 { + 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 +pub 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..70c52ac38b0 --- /dev/null +++ b/noir_stdlib/src/ops/bit.nr @@ -0,0 +1,344 @@ +// docs:start:not-trait +pub 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 +pub 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 u1 { + fn bitor(self, other: u1) -> u1 { + 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 +pub 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 u1 { + fn bitand(self, other: u1) -> u1 { + 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 +pub 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 u1 { + fn bitxor(self, other: u1) -> u1 { + 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 +pub 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 +pub 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/ops/mod.nr b/noir_stdlib/src/ops/mod.nr new file mode 100644 index 00000000000..0e3a2467c60 --- /dev/null +++ b/noir_stdlib/src/ops/mod.nr @@ -0,0 +1,5 @@ +pub(crate) mod arith; +pub(crate) mod bit; + +pub use arith::{Add, Div, Mul, Neg, Rem, Sub}; +pub use bit::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; diff --git a/noir_stdlib/src/option.nr b/noir_stdlib/src/option.nr new file mode 100644 index 00000000000..0a62e412849 --- /dev/null +++ b/noir_stdlib/src/option.nr @@ -0,0 +1,232 @@ +use crate::cmp::{Eq, Ord, Ordering}; +use crate::default::Default; +use crate::hash::{Hash, Hasher}; + +pub struct Option { + _is_some: bool, + _value: T, +} + +impl Option { + /// Constructs a None value + pub fn none() -> Self { + Self { _is_some: false, _value: crate::mem::zeroed() } + } + + /// Constructs a Some wrapper around the given value + pub fn some(_value: T) -> Self { + Self { _is_some: true, _value } + } + + /// True if this Option is None + pub fn is_none(self) -> bool { + !self._is_some + } + + /// True if this Option is Some + pub fn is_some(self) -> bool { + self._is_some + } + + /// Asserts `self.is_some()` and returns the wrapped value. + pub fn unwrap(self) -> T { + assert(self._is_some); + self._value + } + + /// Returns the inner value without asserting `self.is_some()` + /// Note that if `self` is `None`, there is no guarantee what value will be returned, + /// only that it will be of type `T`. + pub fn unwrap_unchecked(self) -> T { + self._value + } + + /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. + pub fn unwrap_or(self, default: T) -> T { + if self._is_some { + self._value + } else { + default + } + } + + /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return + /// a default value. + pub fn unwrap_or_else(self, default: fn[Env]() -> T) -> T { + if self._is_some { + self._value + } else { + default() + } + } + + /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value + pub fn expect(self, message: fmtstr) -> T { + assert(self.is_some(), message); + self._value + } + + /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. + pub fn map(self, f: fn[Env](T) -> U) -> Option { + if self._is_some { + Option::some(f(self._value)) + } else { + Option::none() + } + } + + /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. + pub fn map_or(self, default: U, f: fn[Env](T) -> U) -> U { + if self._is_some { + f(self._value) + } else { + default + } + } + + /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. + pub fn map_or_else(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U { + if self._is_some { + f(self._value) + } else { + default() + } + } + + /// Returns None if self is None. Otherwise, this returns `other`. + pub fn and(self, other: Self) -> Self { + if self.is_none() { + Option::none() + } else { + other + } + } + + /// 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`. + pub fn and_then(self, f: fn[Env](T) -> Option) -> Option { + if self._is_some { + f(self._value) + } else { + Option::none() + } + } + + /// If self is Some, return self. Otherwise, return `other`. + pub fn or(self, other: Self) -> Self { + if self._is_some { + self + } else { + other + } + } + + /// If self is Some, return self. Otherwise, return `default()`. + pub fn or_else(self, default: fn[Env]() -> Self) -> Self { + if self._is_some { + self + } else { + default() + } + } + + // 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. + pub fn xor(self, other: Self) -> Self { + if self._is_some { + if other._is_some { + Option::none() + } else { + self + } + } else if other._is_some { + other + } else { + Option::none() + } + } + + /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. + /// Otherwise, this returns `None` + pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self { + if self._is_some { + if predicate(self._value) { + self + } else { + Option::none() + } + } else { + Option::none() + } + } + + /// Flattens an Option> into a Option. + /// This returns None if the outer Option is None. Otherwise, this returns the inner Option. + pub fn flatten(option: Option>) -> Option { + if option._is_some { + option._value + } else { + Option::none() + } + } +} + +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/panic.nr b/noir_stdlib/src/panic.nr new file mode 100644 index 00000000000..833c1f3dcfc --- /dev/null +++ b/noir_stdlib/src/panic.nr @@ -0,0 +1,4 @@ +pub fn panic(message: fmtstr) -> U { + assert(false, message); + crate::mem::zeroed() +} diff --git a/noir_stdlib/src/prelude.nr b/noir_stdlib/src/prelude.nr new file mode 100644 index 00000000000..a4a6c35b615 --- /dev/null +++ b/noir_stdlib/src/prelude.nr @@ -0,0 +1,10 @@ +pub use crate::{assert_constant, print, println}; +pub use crate::cmp::{Eq, Ord}; +pub use crate::collections::bounded_vec::BoundedVec; +pub use crate::collections::vec::Vec; +pub use crate::convert::{From, Into}; +pub use crate::default::Default; +pub use crate::meta::{derive, derive_via}; +pub use crate::option::Option; +pub use crate::panic::panic; +pub use crate::uint128::U128; 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/sha256.nr b/noir_stdlib/src/sha256.nr new file mode 100644 index 00000000000..9e07b690c4c --- /dev/null +++ b/noir_stdlib/src/sha256.nr @@ -0,0 +1,10 @@ +// This file is kept for backwards compatibility. +#[deprecated] +pub fn digest(msg: [u8; N]) -> [u8; 32] { + crate::hash::sha256::digest(msg) +} + +#[deprecated] +pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { + crate::hash::sha256::sha256_var(msg, message_size) +} diff --git a/noir_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr new file mode 100644 index 00000000000..27b53f4395f --- /dev/null +++ b/noir_stdlib/src/sha512.nr @@ -0,0 +1,5 @@ +// This file is kept for backwards compatibility. +#[deprecated] +pub fn digest(msg: [u8; N]) -> [u8; 64] { + crate::hash::sha512::digest(msg) +} diff --git a/noir_stdlib/src/slice.nr b/noir_stdlib/src/slice.nr new file mode 100644 index 00000000000..a8815681d6d --- /dev/null +++ b/noir_stdlib/src/slice.nr @@ -0,0 +1,138 @@ +use crate::append::Append; + +impl [T] { + /// Returns the length of the slice. + #[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. + #[builtin(slice_push_back)] + pub fn push_back(self, elem: T) -> Self {} + + /// Push a new element to the front of the slice, returning a + /// new slice with a length one greater than the + /// original unmodified slice. + #[builtin(slice_push_front)] + pub fn push_front(self, elem: T) -> Self {} + + /// Remove the last element of the slice, returning the + /// popped slice and the element in a tuple + #[builtin(slice_pop_back)] + pub fn pop_back(self) -> (Self, T) {} + + /// Remove the first element of the slice, returning the + /// element and the popped slice in a tuple + #[builtin(slice_pop_front)] + pub fn pop_front(self) -> (T, Self) {} + + /// Insert an element at a specified index, shifting all elements + /// after it to the right + #[builtin(slice_insert)] + 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: 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. + pub fn append(mut self, other: Self) -> Self { + for elem in other { + self = self.push_back(elem); + } + self + } + + pub fn as_array(self) -> [T; N] { + assert(self.len() == N); + + let mut array = [crate::mem::zeroed(); N]; + for i in 0..N { + array[i] = self[i]; + } + array + } + + // Apply a function to each element of the slice, returning a new slice + // containing the mapped elements. + pub fn map(self, f: fn[Env](T) -> U) -> [U] { + let mut ret = &[]; + for elem in self { + ret = ret.push_back(f(elem)); + } + ret + } + + // Apply a function to each element of the slice and an accumulator value, + // returning the final accumulated value. This function is also sometimes + // called `foldl`, `fold_left`, `reduce`, or `inject`. + pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U { + for elem in self { + accumulator = f(accumulator, elem); + } + accumulator + } + + // Apply a function to each element of the slice and an accumulator value, + // returning the final accumulated value. Unlike fold, reduce uses the first + // element of the given slice as its starting accumulator value. + pub fn reduce(self, f: fn[Env](T, T) -> T) -> T { + let mut accumulator = self[0]; + for i in 1..self.len() { + accumulator = f(accumulator, self[i]); + } + accumulator + } + + // Returns a new slice containing only elements for which the given predicate + // returns true. + pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self { + let mut ret = &[]; + for elem in self { + if predicate(elem) { + ret = ret.push_back(elem); + } + } + ret + } + + // Flatten each element in the slice into one value, separated by `separator`. + pub fn join(self, separator: T) -> T + where + T: Append, + { + let mut ret = T::empty(); + + if self.len() != 0 { + ret = self[0]; + + for i in 1..self.len() { + ret = ret.append(separator).append(self[i]); + } + } + + ret + } + + // Returns true if all elements in the slice satisfy the predicate + pub fn all(self, predicate: fn[Env](T) -> bool) -> bool { + let mut ret = true; + for elem in self { + ret &= predicate(elem); + } + ret + } + + // Returns true if any element in the slice satisfies the predicate + pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { + let mut ret = false; + for elem in self { + ret |= predicate(elem); + } + ret + } +} diff --git a/noir_stdlib/src/string.nr b/noir_stdlib/src/string.nr new file mode 100644 index 00000000000..18fb449626a --- /dev/null +++ b/noir_stdlib/src/string.nr @@ -0,0 +1,19 @@ +use crate::collections::vec::Vec; +use crate::convert::From; + +impl str { + /// Converts the given string into a byte array + #[builtin(str_as_bytes)] + pub fn as_bytes(self) -> [u8; N] {} + + /// return a byte vector of the str content + pub fn as_bytes_vec(self: Self) -> Vec { + Vec::from_slice(self.as_bytes().as_slice()) + } +} + +impl From<[u8; N]> for str { + fn from(bytes: [u8; N]) -> Self { + bytes.as_str_unchecked() + } +} diff --git a/noir_stdlib/src/test.nr b/noir_stdlib/src/test.nr new file mode 100644 index 00000000000..4d6954913d1 --- /dev/null +++ b/noir_stdlib/src/test.nr @@ -0,0 +1,50 @@ +#[oracle(create_mock)] +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) {} + +#[oracle(set_mock_times)] +unconstrained fn set_mock_times_oracle(id: Field, times: u64) {} + +#[oracle(clear_mock)] +unconstrained fn clear_mock_oracle(id: Field) {} + +pub struct OracleMock { + id: Field, +} + +impl OracleMock { + pub unconstrained fn mock(name: str) -> Self { + Self { id: create_mock_oracle(name) } + } + + pub unconstrained fn with_params

(self, params: P) -> Self { + set_mock_params_oracle(self.id, params); + self + } + + pub unconstrained fn get_last_params

(self) -> P { + get_mock_last_params_oracle(self.id) + } + + pub unconstrained fn returns(self, returns: R) -> Self { + set_mock_returns_oracle(self.id, returns); + self + } + + pub unconstrained fn times(self, times: u64) -> Self { + set_mock_times_oracle(self.id, times); + self + } + + pub unconstrained fn clear(self) { + clear_mock_oracle(self.id); + } +} diff --git a/noir_stdlib/src/uint128.nr b/noir_stdlib/src/uint128.nr new file mode 100644 index 00000000000..9aa01e1ea52 --- /dev/null +++ b/noir_stdlib/src/uint128.nr @@ -0,0 +1,572 @@ +use crate::cmp::{Eq, Ord, Ordering}; +use crate::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Rem, Shl, Shr, Sub}; +use super::{convert::AsPrimitive, default::Default}; + +global pow64: Field = 18446744073709551616; //2^64; +global pow63: Field = 9223372036854775808; // 2^63; +pub struct U128 { + pub(crate) lo: Field, + pub(crate) hi: Field, +} + +impl U128 { + + pub fn from_u64s_le(lo: u64, hi: u64) -> U128 { + // in order to handle multiplication, we need to represent the product of two u64 without overflow + assert(crate::field::modulus_num_bits() as u32 > 128); + U128 { lo: lo as Field, hi: hi as Field } + } + + pub fn from_u64s_be(hi: u64, lo: u64) -> 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; + for i in 0..8 { + lo += (bytes[i] as Field) * base; + base *= 256; + } + let mut hi = 0; + base = 1; + for i in 8..16 { + hi += (bytes[i] as Field) * base; + base *= 256; + } + U128 { lo, hi } + } + + pub fn to_be_bytes(self: Self) -> [u8; 16] { + let lo: [u8; 8] = self.lo.to_be_bytes(); + let hi: [u8; 8] = self.hi.to_be_bytes(); + let mut bytes = [0; 16]; + for i in 0..8 { + bytes[i] = hi[i]; + bytes[i + 8] = lo[i]; + } + bytes + } + + pub fn to_le_bytes(self: Self) -> [u8; 16] { + let lo: [u8; 8] = self.lo.to_le_bytes(); + let hi: [u8; 8] = self.hi.to_le_bytes(); + let mut bytes = [0; 16]; + for i in 0..8 { + bytes[i] = lo[i]; + bytes[i + 8] = hi[i]; + } + bytes + } + + pub fn from_hex(hex: str) -> U128 { + let N = N as u32; + let bytes = hex.as_bytes(); + // string must starts with "0x" + assert((bytes[0] == 48) & (bytes[1] == 120), "Invalid hexadecimal string"); + assert(N < 35, "Input does not fit into a U128"); + + let mut lo = 0; + let mut hi = 0; + let mut base = 1; + if N <= 18 { + for i in 0..N - 2 { + lo += U128::decode_ascii(bytes[N - i - 1]) * base; + base = base * 16; + } + } else { + for i in 0..16 { + lo += U128::decode_ascii(bytes[N - i - 1]) * base; + base = base * 16; + } + base = 1; + for i in 17..N - 1 { + hi += U128::decode_ascii(bytes[N - i]) * base; + base = base * 16; + } + } + 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' + } + + pub(crate) fn decode_ascii(ascii: u8) -> Field { + ( + if ascii < 58 { + ascii - 48 + } else { + /// Safety: optionally adds 32 and then check (below) the result is in 'a..f' range + let ascii = + ascii + 32 * (unsafe { 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 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 { + 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::one(), r - b) + } + } + } + + pub fn from_integer(i: T) -> U128 + where + T: AsPrimitive, + { + let f = i.as_(); + // Reject values which would overflow a u128 + f.assert_max_bit_size::<128>(); + let lo = f as u64 as Field; + let hi = (f - lo) / pow64; + U128 { lo, hi } + } + + pub fn to_integer(self) -> T + where + Field: AsPrimitive, + { + AsPrimitive::as_(self.lo + self.hi * pow64) + } + + 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 = self.lo * b.hi + self.hi * b.lo + carry; + let hi = high as u64 as Field; + U128 { lo, hi } + } +} + +impl Add for U128 { + fn add(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 = self.hi + b.hi + carry; + let hi = high as u64 as Field; + assert(hi == high, "attempt to add with overflow"); + U128 { lo, hi } + } +} + +impl Sub for U128 { + fn sub(self: Self, b: U128) -> U128 { + let low = pow64 + self.lo - b.lo; + let lo = low as u64 as Field; + let borrow = (low == lo) as Field; + let high = self.hi - b.hi - borrow; + let hi = high as u64 as Field; + assert(hi == high, "attempt to subtract with underflow"); + U128 { lo, hi } + } +} + +impl Mul for U128 { + fn mul(self: Self, b: U128) -> U128 { + assert(self.hi * b.hi == 0, "attempt to multiply with overflow"); + 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 hi = high as u64 as Field; + assert(hi == high, "attempt to multiply with overflow"); + U128 { lo, hi } + } +} + +impl Div for U128 { + fn div(self: Self, b: U128) -> U128 { + /// Safety: euclidian division is asserted to be correct: assert(a == b * q + r); and assert(r < b); + /// Furthermore, U128 addition and multiplication ensures that b * q + r does not overflow + unsafe { + let (q, r) = self.unconstrained_div(b); + let a = b * q + r; + assert_eq(self, a); + assert(r < b); + q + } + } +} + +impl Rem for U128 { + fn rem(self: Self, b: U128) -> U128 { + /// Safety: cf div() above + unsafe { + let (q, r) = self.unconstrained_div(b); + let a = b * q + r; + assert_eq(self, a); + assert(r < b); + + r + } + } +} + +impl Eq for U128 { + fn eq(self: Self, b: U128) -> bool { + (self.lo == b.lo) & (self.hi == b.hi) + } +} + +impl Ord for U128 { + fn cmp(self, other: Self) -> Ordering { + let hi_ordering = (self.hi as u64).cmp((other.hi as u64)); + let lo_ordering = (self.lo as u64).cmp((other.lo as u64)); + + if hi_ordering == Ordering::equal() { + lo_ordering + } else { + hi_ordering + } + } +} + +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, + } + } +} + +impl BitAnd for U128 { + fn bitand(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, + } + } +} + +impl BitXor for U128 { + fn bitxor(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, + } + } +} + +impl Shl for U128 { + fn shl(self, other: u8) -> U128 { + assert(other < 128, "attempt to shift left with overflow"); + let exp_bits: [u1; 7] = (other as Field).to_be_bits(); + + let mut r: Field = 2; + let mut y: Field = 1; + for i in 1..8 { + let bit = exp_bits[7 - i] as Field; + y = bit * (r * y) + (1 - bit) * y; + r *= r; + } + self.wrapping_mul(U128::from_integer(y)) + } +} + +impl Shr for U128 { + fn shr(self, other: u8) -> U128 { + assert(other < 128, "attempt to shift right with overflow"); + let exp_bits: [u1; 7] = (other as Field).to_be_bits(); + + let mut r: Field = 2; + let mut y: Field = 1; + for i in 1..8 { + let bit = exp_bits[7 - i] as Field; + y = bit * (r * y) + (1 - bit) * y; + r *= r; + } + self / U128::from_integer(y) + } +} + +impl Default for U128 { + fn default() -> Self { + U128::zero() + } +} + +mod tests { + use crate::default::Default; + use crate::ops::Not; + use crate::uint128::{pow63, pow64, U128}; + + #[test] + fn test_not(lo: u64, hi: u64) { + let num = U128::from_u64s_le(lo, hi); + let not_num = num.not(); + + assert_eq(not_num.hi, (hi.not() as Field)); + assert_eq(not_num.lo, (lo.not() as Field)); + + 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: [u8; 17] = b.to_le_bytes(); + 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); + /// Safety: testing context + 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 + /// Safety: testing context + unsafe { + let (c, d) = a.unconstrained_div(b); + assert_eq((c, d), (a, U128::zero())); + } + + // Check where b is a multiple of a + /// Safety: testing context + 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(); + /// Safety: testing context + 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); + /// Safety: testing context + 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 integer_conversions_fuzz(lo: u64, hi: u64) { + let start: Field = (lo as Field) + pow64 * (hi as Field); + 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), + ), + ); + } + + #[test] + fn test_default() { + assert_eq(U128::default(), U128::zero()); + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000000..00036838f9b --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "@noir-lang/root", + "private": true, + "workspaces": [ + "compiler/wasm", + "compiler/integration-tests", + "tooling/noir_js_types", + "tooling/noirc_abi_wasm", + "tooling/noir_js", + "tooling/noir_codegen", + "acvm-repo/acvm_js", + "docs" + ], + "scripts": { + "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 ./target ./packages", + "clean": "yarn clean:workspaces && yarn clean:root", + "lint": "yarn workspaces foreach --verbose run lint", + "spellcheck": "cspell '**/*.{md,rs}' -c ./cspell.json", + "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.4.1", + "cspell": "^8.3.2", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", + "mocha": "^10.2.0", + "prettier": "3.2.5", + "ts-node": "^10.9.1", + "typescript": "^5.4.2" + }, + "packageManager": "yarn@3.6.4" +} diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000000..963f1af26d9 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,78 @@ +{ + "release-type": "simple", + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "prerelease": true, + "prerelease-type": "beta", + "pull-request-title-pattern": "chore: Release Noir(${version})", + "group-pull-request-title-pattern": "chore: Release Noir(${version})", + "packages": { + ".": { + "release-type": "simple", + "versioning": "prerelease", + "component": "noir", + "package-name": "noir", + "include-component-in-tag": false, + "extra-files": [ + "Cargo.toml", + "acvm-repo/acir/Cargo.toml", + "acvm-repo/acir_field/Cargo.toml", + "acvm-repo/acvm/Cargo.toml", + "acvm-repo/acvm_js/Cargo.toml", + "acvm-repo/blackbox_solver/Cargo.toml", + "acvm-repo/bn254_blackbox_solver/Cargo.toml", + "acvm-repo/brillig/Cargo.toml", + "acvm-repo/brillig_vm/Cargo.toml", + { + "type": "json", + "path": "acvm-repo/acvm_js/package.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": "acvm-repo/acvm_js/package.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": "compiler/wasm/package.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": "tooling/noir_codegen/package.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": "tooling/noir_js/package.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": "tooling/noir_js_backend_barretenberg/package.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": "tooling/noir_js_types/package.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": "tooling/noirc_abi_wasm/package.json", + "jsonpath": "$.version" + }, + { + "type": "json", + "path": "docs/docs/package.json", + "jsonpath": "$.version" + } + ] + } + }, + "plugins": [ + "sentence-case" + ], + "bootstrap-sha": "690cfc0468de0b9aee53ccfe832c71c16e61e5fc" +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 00000000000..e647d5cbf46 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "1.75.0" +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/bump-bb.sh b/scripts/bump-bb.sh new file mode 100755 index 00000000000..661a8eb9d43 --- /dev/null +++ b/scripts/bump-bb.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +BB_VERSION=$1 + +sed -i.bak "s/^VERSION=.*/VERSION=\"$BB_VERSION\"/" ./scripts/install_bb.sh && rm ./scripts/install_bb.sh.bak + +tmp=$(mktemp) +INTEGRATION_TESTS_PACKAGE_JSON=./compiler/integration-tests/package.json +jq --arg v $BB_VERSION '.dependencies."@aztec/bb.js" = $v' $INTEGRATION_TESTS_PACKAGE_JSON > $tmp && mv $tmp $INTEGRATION_TESTS_PACKAGE_JSON + +YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install diff --git a/scripts/check-critical-libraries.sh b/scripts/check-critical-libraries.sh new file mode 100755 index 00000000000..f8e474d23de --- /dev/null +++ b/scripts/check-critical-libraries.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -e + +# Run relative to repo root +cd $(dirname "$0")/../ + +if [[ -z $1 ]]; then + echo "Must specify Noir release to test against" >&2 + echo "usage: ./check-critical-libraries.sh " >&2 + exit 1 +fi +noirup -v $1 + +CRITICAL_LIBRARIES=$(grep -v "^#\|^$" ./CRITICAL_NOIR_LIBRARIES) +readarray -t REPOS_TO_CHECK < <(echo "$CRITICAL_LIBRARIES") + +getLatestReleaseTagForRepo() { + REPO_NAME=$1 + TAG=$(gh release list -R $REPO_NAME --json 'tagName,isLatest' -q '.[] | select(.isLatest == true).tagName') + if [[ -z $TAG ]]; then + echo "$REPO_NAME has no valid release" >&2 + exit 1 + fi + echo $TAG +} + +for REPO in ${REPOS_TO_CHECK[@]}; do + echo $REPO + TMP_DIR=$(mktemp -d) + + TAG=$(getLatestReleaseTagForRepo $REPO) + git clone $REPO -c advice.detachedHead=false --depth 1 --branch $TAG $TMP_DIR + + nargo test -q --program-dir $TMP_DIR + + rm -rf $TMP_DIR +done 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..3d1dc038ab8 --- /dev/null +++ b/scripts/install_bb.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +VERSION="0.66.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/redo-typo-pr.sh b/scripts/redo-typo-pr.sh new file mode 100755 index 00000000000..4b3b93b48ed --- /dev/null +++ b/scripts/redo-typo-pr.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +set -eux + +# Configuration +ORIGINAL_PR_NUMBER=$1 +REPO='noir-lang/noir' +NEW_BRANCH="chore/typo-redo-$ORIGINAL_PR_NUMBER" +AUTHOR=`gh pr view $ORIGINAL_PR_NUMBER --json author --jq '.author.login'` + +# Step 1: Checkout the PR locally +echo "Checking out PR #$ORIGINAL_PR_NUMBER" +gh pr checkout $ORIGINAL_PR_NUMBER + +# Step 2: Create a new local branch +echo "Creating new local branch $NEW_BRANCH" +git checkout -b $NEW_BRANCH + +# Step 3: Squash commits +echo "Squashing new local branch $NEW_BRANCH" +git reset --soft master +git add . +git commit -m "chore: typo fixes" + +# Step 4: Push the new branch to GitHub +echo "Pushing new branch $NEW_BRANCH to GitHub" +git push origin $NEW_BRANCH + +# Step 5: create a new pull request +echo "Creating a new pull request for $NEW_BRANCH" +gh pr create --base master --head $NEW_BRANCH --title "chore: redo typo PR by $AUTHOR" --body "Thanks $AUTHOR for https://github.com/$REPO/pull/$ORIGINAL_PR_NUMBER. Our policy is to redo typo changes to dissuade metric farming. This is an automated script." + +# Step 6: Close the original PR +echo "Closing original PR #$ORIGINAL_PR_NUMBER" +gh pr close $ORIGINAL_PR_NUMBER + +echo "Script completed." diff --git a/scripts/update-acvm-workspace-versions.sh b/scripts/update-acvm-workspace-versions.sh new file mode 100755 index 00000000000..3478333f05a --- /dev/null +++ b/scripts/update-acvm-workspace-versions.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Path to the top-level Cargo.toml +TOP_LEVEL_CARGO_TOML="Cargo.toml" + +# Temporary file to store paths +TEMP_PATHS_FILE="temp_paths.txt" + +# Extract local dependencies paths that start with "acvm-repo" +grep 'path = "acvm-repo' "$TOP_LEVEL_CARGO_TOML" | sed -E 's/.*path = "([^"]+)".*/\1/' > "$TEMP_PATHS_FILE" + +# Read each path and update the version in the top level workspace Cargo.toml file +# to match the version in the component's Cargo.toml +while IFS= read -r component_path; do + # Extract the component name + # This is acir_field for example or stdlib + component_name=$(basename "$component_path") + + # Extract the version from the component's Cargo.toml + # This is acvm-repo/acir_field for example + component_version=$(grep '^version =' "$component_path/Cargo.toml" | sed -E 's/version = "([^"]+)"/\1/') + + if [ -z "$component_version" ]; then + echo "Error: Unable to extract version for $component_name from $component_path/Cargo.toml" + continue + fi + + # Update the version in the top-level Cargo.toml + sed -i.bak -E "s|($component_name[[:space:]]*=[[:space:]]*\{[[:space:]]*version[[:space:]]*=[[:space:]]*\")([^\"]+)(\".*)|\1$component_version\3|" "$TOP_LEVEL_CARGO_TOML" + + if [ $? -ne 0 ]; then + echo "Error: Unable to update version for $component_name in $TOP_LEVEL_CARGO_TOML" + else + echo "Version for $component_name updated successfully to $component_version in $TOP_LEVEL_CARGO_TOML" + fi +done < "$TEMP_PATHS_FILE" + +# Remove temporary file and backup file +rm "$TEMP_PATHS_FILE" +rm "${TOP_LEVEL_CARGO_TOML}.bak" diff --git a/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/test_programs/.gitignore b/test_programs/.gitignore new file mode 100644 index 00000000000..cc2eb528c3b --- /dev/null +++ b/test_programs/.gitignore @@ -0,0 +1,4 @@ +acir_artifacts +execution_success/**/crs +./Nargo.toml +rebuild.log \ No newline at end of file diff --git a/test_programs/README.md b/test_programs/README.md new file mode 100644 index 00000000000..71e609ebf24 --- /dev/null +++ b/test_programs/README.md @@ -0,0 +1,43 @@ +# Integration test directory structure + +Integration tests for the Noir compiler are broken down into the following directories: + +- `compile_failure`: programs which are not valid or unsatisfiable Noir code and so the compiler should reject. +- `compile_success_empty`: programs which are valid satisfiable Noir code but have no opcodes. +- `compile_success_contract`: contracts which are valid Noir code. +- `execution_success`: programs which are valid Noir satisfiable code and have opcodes. + +The current testing flow can be thought of as shown: +```mermaid +flowchart TD + + subgraph compile_failure + A1[Attempt to compile] --> A2[Assert compilation fails] + end + + subgraph compile_success_empty + B1[Attempt to compile] --> B2[Assert compilation succeeds] + B2 --> B3[Assert empty circuit] + end + + subgraph execution_success + C1[Attempt to compile] --> C2[Assert compilation succeeds] + C2 --> C3[Write circuit to file] + C3 --> C4[Assert execution succeeds] + C4 --> C5[Write witness to file] + + C6[Publish witness + circuit as artifact] + C3 --> C6 + C5 --> C6 + end + + subgraph compile_success_contract + D1[Attempt to compile] --> D2[Assert compilation succeeds] + end +``` + +## `execution_success` vs `compile_success_empty` + +Note that `execution_success` and `compile_success_empty` are distinct as `compile_success_empty` is expected to compile down to an empty circuit. This may not be possible for some argument-less circuits in the situation where instructions have side-effects or certain compiler optimizations are missing, but once moved to `compile_success_empty` a program compiling down to a non-empty circuit is a compiler regression. + + diff --git a/test_programs/benchmarks/bench_eddsa_poseidon/Nargo.toml b/test_programs/benchmarks/bench_eddsa_poseidon/Nargo.toml new file mode 100644 index 00000000000..6c754f1d107 --- /dev/null +++ b/test_programs/benchmarks/bench_eddsa_poseidon/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "bench_eddsa_poseidon" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] +ec = { tag = "v0.1.2", git = "https://github.com/noir-lang/ec" } diff --git a/test_programs/benchmarks/bench_eddsa_poseidon/Prover.toml b/test_programs/benchmarks/bench_eddsa_poseidon/Prover.toml new file mode 100644 index 00000000000..8cfb63cd80e --- /dev/null +++ b/test_programs/benchmarks/bench_eddsa_poseidon/Prover.toml @@ -0,0 +1,6 @@ +msg = 789 +pub_key_x = "0x16b051f37589e0dcf4ad3c415c090798c10d3095bedeedabfcc709ad787f3507" +pub_key_y = "0x062800ac9e60839fab9218e5ed9d541f4586e41275f4071816a975895d349a5e" +r8_x = "0x163814666f04c4d2969059a6b63ee26a0f9f0f81bd5957b0796e2e8f4a8a2f06" +r8_y = "0x1255b17d9e4bfb81831625b788f8a1665128079ac4b6c8c3cd1b857666a05a54" +s = "1230930278088778318663840827871215383007447616379808164955640681455510074924" \ No newline at end of file diff --git a/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr b/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr new file mode 100644 index 00000000000..c4a1d4b51f5 --- /dev/null +++ b/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr @@ -0,0 +1,63 @@ +use std::default::Default; +use std::hash::Hasher; +use std::hash::poseidon::PoseidonHasher; + +use ec::consts::te::baby_jubjub; +use ec::tecurve::affine::Point as TEPoint; + + +fn main( + msg: pub Field, + pub_key_x: Field, + pub_key_y: Field, + r8_x: Field, + r8_y: Field, + s: Field, +) -> pub bool { + eddsa_verify::(pub_key_x, pub_key_y, s, r8_x, r8_y, msg) +} + +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(); + + let pub_key = TEPoint::new(pub_key_x, pub_key_y); + assert(bjj.curve.contains(pub_key)); + + let signature_r8 = TEPoint::new(signature_r8_x, signature_r8_y); + assert(bjj.curve.contains(signature_r8)); + // Ensure S < Subgroup Order + assert(signature_s.lt(bjj.suborder)); + // Calculate the h = H(R, A, msg) + 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); + let pub_key_mul_4 = bjj.curve.add(pub_key_mul_2, pub_key_mul_2); + let pub_key_mul_8 = bjj.curve.add(pub_key_mul_4, pub_key_mul_4); + // We check that A8 is not zero. + assert(!pub_key_mul_8.is_zero()); + // Compute the right side: R8 + h * A8 + let right = bjj.curve.add(signature_r8, bjj.curve.mul(hash, pub_key_mul_8)); + // Calculate left side of equation left = S * B8 + let left = bjj.curve.mul(signature_s, bjj.base8); + + left.eq(right) +} diff --git a/test_programs/benchmarks/bench_poseidon2_hash/Nargo.toml b/test_programs/benchmarks/bench_poseidon2_hash/Nargo.toml new file mode 100644 index 00000000000..47bf6af3c27 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon2_hash/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_poseidon2_hash" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_poseidon2_hash/Prover.toml b/test_programs/benchmarks/bench_poseidon2_hash/Prover.toml new file mode 100644 index 00000000000..66779dea9d7 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon2_hash/Prover.toml @@ -0,0 +1 @@ +input = [1,2] diff --git a/test_programs/benchmarks/bench_poseidon2_hash/src/main.nr b/test_programs/benchmarks/bench_poseidon2_hash/src/main.nr new file mode 100644 index 00000000000..a3528253f5d --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon2_hash/src/main.nr @@ -0,0 +1,5 @@ +use std::hash::poseidon2; + +fn main(input: [Field; 2]) -> pub Field { + poseidon2::Poseidon2::hash(input, input.len()) +} diff --git a/test_programs/benchmarks/bench_poseidon2_hash_100/Nargo.toml b/test_programs/benchmarks/bench_poseidon2_hash_100/Nargo.toml new file mode 100644 index 00000000000..4a8bd608939 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon2_hash_100/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_poseidon2_hash_100" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_poseidon2_hash_100/Prover.toml b/test_programs/benchmarks/bench_poseidon2_hash_100/Prover.toml new file mode 100644 index 00000000000..542b4a08dd6 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon2_hash_100/Prover.toml @@ -0,0 +1,102 @@ +input = [ + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], +] \ No newline at end of file diff --git a/test_programs/benchmarks/bench_poseidon2_hash_100/src/main.nr b/test_programs/benchmarks/bench_poseidon2_hash_100/src/main.nr new file mode 100644 index 00000000000..66a785f446a --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon2_hash_100/src/main.nr @@ -0,0 +1,12 @@ +use std::hash::poseidon2; + +global SIZE: u32 = 100; + +fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { + let mut results: [Field; SIZE] = [0; SIZE]; + for i in 0..SIZE { + results[i] = poseidon2::Poseidon2::hash(input[i], 2); + } + + results +} diff --git a/test_programs/benchmarks/bench_poseidon2_hash_30/Nargo.toml b/test_programs/benchmarks/bench_poseidon2_hash_30/Nargo.toml new file mode 100644 index 00000000000..0a245bb572e --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon2_hash_30/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_poseidon2_hash_30" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_poseidon2_hash_30/Prover.toml b/test_programs/benchmarks/bench_poseidon2_hash_30/Prover.toml new file mode 100644 index 00000000000..7792a9ab8e3 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon2_hash_30/Prover.toml @@ -0,0 +1,32 @@ +input = [ + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], +] \ No newline at end of file diff --git a/test_programs/benchmarks/bench_poseidon2_hash_30/src/main.nr b/test_programs/benchmarks/bench_poseidon2_hash_30/src/main.nr new file mode 100644 index 00000000000..2e72ebc3519 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon2_hash_30/src/main.nr @@ -0,0 +1,12 @@ +use std::hash::poseidon2; + +global SIZE: u32 = 30; + +fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { + let mut results: [Field; SIZE] = [0; SIZE]; + for i in 0..SIZE { + results[i] = poseidon2::Poseidon2::hash(input[i], 2); + } + + results +} diff --git a/test_programs/benchmarks/bench_poseidon_hash/Nargo.toml b/test_programs/benchmarks/bench_poseidon_hash/Nargo.toml new file mode 100644 index 00000000000..9024d9a7301 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_poseidon_hash" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_poseidon_hash/Prover.toml b/test_programs/benchmarks/bench_poseidon_hash/Prover.toml new file mode 100644 index 00000000000..66779dea9d7 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash/Prover.toml @@ -0,0 +1 @@ +input = [1,2] diff --git a/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_100/Nargo.toml b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_100/Nargo.toml new file mode 100644 index 00000000000..b23716b2a20 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_100/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_poseidon_hash_100" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_100/Prover.toml b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_100/Prover.toml new file mode 100644 index 00000000000..542b4a08dd6 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_100/Prover.toml @@ -0,0 +1,102 @@ +input = [ + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], +] \ No newline at end of file diff --git a/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_100/src/main.nr b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_100/src/main.nr new file mode 100644 index 00000000000..75d853941e5 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_100/src/main.nr @@ -0,0 +1,12 @@ +use std::hash; + +global SIZE: u32 = 100; + +fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { + let mut results: [Field; SIZE] = [0; SIZE]; + for i in 0..SIZE { + results[i] = hash::poseidon::bn254::hash_2(input[i]); + } + + results +} diff --git a/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_30/Nargo.toml b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_30/Nargo.toml new file mode 100644 index 00000000000..dbcbc07b1ba --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_30/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_poseidon_hash_30" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_30/Prover.toml b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_30/Prover.toml new file mode 100644 index 00000000000..7792a9ab8e3 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_30/Prover.toml @@ -0,0 +1,32 @@ +input = [ + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], +] \ No newline at end of file diff --git a/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_30/src/main.nr b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_30/src/main.nr new file mode 100644 index 00000000000..d4f357e11f9 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash/bench_poseidon_hash_30/src/main.nr @@ -0,0 +1,12 @@ +use std::hash; + +global SIZE: u32 = 30; + +fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { + let mut results: [Field; SIZE] = [0; SIZE]; + for i in 0..SIZE { + results[i] = hash::poseidon::bn254::hash_2(input[i]); + } + + results +} diff --git a/test_programs/benchmarks/bench_poseidon_hash/src/main.nr b/test_programs/benchmarks/bench_poseidon_hash/src/main.nr new file mode 100644 index 00000000000..9900e91c1d7 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash/src/main.nr @@ -0,0 +1,5 @@ +use std::hash::poseidon; + +fn main(input: [Field; 2]) -> pub Field { + poseidon::bn254::hash_2(input) +} diff --git a/test_programs/benchmarks/bench_poseidon_hash_100/Nargo.toml b/test_programs/benchmarks/bench_poseidon_hash_100/Nargo.toml new file mode 100644 index 00000000000..b23716b2a20 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash_100/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_poseidon_hash_100" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_poseidon_hash_100/Prover.toml b/test_programs/benchmarks/bench_poseidon_hash_100/Prover.toml new file mode 100644 index 00000000000..542b4a08dd6 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash_100/Prover.toml @@ -0,0 +1,102 @@ +input = [ + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], +] \ No newline at end of file diff --git a/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr b/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr new file mode 100644 index 00000000000..75d853941e5 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr @@ -0,0 +1,12 @@ +use std::hash; + +global SIZE: u32 = 100; + +fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { + let mut results: [Field; SIZE] = [0; SIZE]; + for i in 0..SIZE { + results[i] = hash::poseidon::bn254::hash_2(input[i]); + } + + results +} diff --git a/test_programs/benchmarks/bench_poseidon_hash_30/Nargo.toml b/test_programs/benchmarks/bench_poseidon_hash_30/Nargo.toml new file mode 100644 index 00000000000..dbcbc07b1ba --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash_30/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_poseidon_hash_30" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_poseidon_hash_30/Prover.toml b/test_programs/benchmarks/bench_poseidon_hash_30/Prover.toml new file mode 100644 index 00000000000..7792a9ab8e3 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash_30/Prover.toml @@ -0,0 +1,32 @@ +input = [ + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], +] \ No newline at end of file diff --git a/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr b/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr new file mode 100644 index 00000000000..d4f357e11f9 --- /dev/null +++ b/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr @@ -0,0 +1,12 @@ +use std::hash; + +global SIZE: u32 = 30; + +fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { + let mut results: [Field; SIZE] = [0; SIZE]; + for i in 0..SIZE { + results[i] = hash::poseidon::bn254::hash_2(input[i]); + } + + results +} diff --git a/test_programs/benchmarks/bench_sha256/Nargo.toml b/test_programs/benchmarks/bench_sha256/Nargo.toml new file mode 100644 index 00000000000..488b94ca858 --- /dev/null +++ b/test_programs/benchmarks/bench_sha256/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_sha256" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_sha256/Prover.toml b/test_programs/benchmarks/bench_sha256/Prover.toml new file mode 100644 index 00000000000..66779dea9d7 --- /dev/null +++ b/test_programs/benchmarks/bench_sha256/Prover.toml @@ -0,0 +1 @@ +input = [1,2] diff --git a/test_programs/benchmarks/bench_sha256/src/main.nr b/test_programs/benchmarks/bench_sha256/src/main.nr new file mode 100644 index 00000000000..c94d359239d --- /dev/null +++ b/test_programs/benchmarks/bench_sha256/src/main.nr @@ -0,0 +1,4 @@ + +fn main(input: [u8; 2]) -> pub [u8; 32] { + std::hash::sha256(input) +} \ No newline at end of file diff --git a/test_programs/benchmarks/bench_sha256_100/Nargo.toml b/test_programs/benchmarks/bench_sha256_100/Nargo.toml new file mode 100644 index 00000000000..d0c90d75088 --- /dev/null +++ b/test_programs/benchmarks/bench_sha256_100/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_sha256_100" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_sha256_100/Prover.toml b/test_programs/benchmarks/bench_sha256_100/Prover.toml new file mode 100644 index 00000000000..542b4a08dd6 --- /dev/null +++ b/test_programs/benchmarks/bench_sha256_100/Prover.toml @@ -0,0 +1,102 @@ +input = [ + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], +] \ No newline at end of file diff --git a/test_programs/benchmarks/bench_sha256_100/src/main.nr b/test_programs/benchmarks/bench_sha256_100/src/main.nr new file mode 100644 index 00000000000..6e4bfc27c8f --- /dev/null +++ b/test_programs/benchmarks/bench_sha256_100/src/main.nr @@ -0,0 +1,10 @@ +global SIZE: u32 = 100; + +fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { + let mut results: [[u8; 32]; SIZE] = [[0; 32]; SIZE]; + for i in 0..SIZE { + results[i] = std::hash::sha256(input[i]); + } + + results +} diff --git a/test_programs/benchmarks/bench_sha256_30/Nargo.toml b/test_programs/benchmarks/bench_sha256_30/Nargo.toml new file mode 100644 index 00000000000..c1dc76df394 --- /dev/null +++ b/test_programs/benchmarks/bench_sha256_30/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_sha256_30" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_sha256_30/Prover.toml b/test_programs/benchmarks/bench_sha256_30/Prover.toml new file mode 100644 index 00000000000..7792a9ab8e3 --- /dev/null +++ b/test_programs/benchmarks/bench_sha256_30/Prover.toml @@ -0,0 +1,32 @@ +input = [ + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], + [1,2], +] \ No newline at end of file diff --git a/test_programs/benchmarks/bench_sha256_30/src/main.nr b/test_programs/benchmarks/bench_sha256_30/src/main.nr new file mode 100644 index 00000000000..0a4288114e3 --- /dev/null +++ b/test_programs/benchmarks/bench_sha256_30/src/main.nr @@ -0,0 +1,10 @@ +global SIZE: u32 = 30; + +fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { + let mut results: [[u8; 32]; SIZE] = [[0; 32]; SIZE]; + for i in 0..SIZE { + results[i] = std::hash::sha256(input[i]); + } + + results +} diff --git a/test_programs/benchmarks/bench_sha256_long/Nargo.toml b/test_programs/benchmarks/bench_sha256_long/Nargo.toml new file mode 100644 index 00000000000..ae66d7ed5a6 --- /dev/null +++ b/test_programs/benchmarks/bench_sha256_long/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_sha256_long" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/benchmarks/bench_sha256_long/Prover.toml b/test_programs/benchmarks/bench_sha256_long/Prover.toml new file mode 100644 index 00000000000..ba4bbc1540d --- /dev/null +++ b/test_programs/benchmarks/bench_sha256_long/Prover.toml @@ -0,0 +1,191 @@ +# 2*64+60=188 bytes +input = [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, +] diff --git a/test_programs/benchmarks/bench_sha256_long/src/main.nr b/test_programs/benchmarks/bench_sha256_long/src/main.nr new file mode 100644 index 00000000000..c47bdc2a561 --- /dev/null +++ b/test_programs/benchmarks/bench_sha256_long/src/main.nr @@ -0,0 +1,7 @@ +// Input size long enough that we have to compress a few times +// and then pad the last block out. +global INPUT_SIZE: u32 = 2 * 64 + 60; + +fn main(input: [u8; INPUT_SIZE]) -> pub [u8; 32] { + std::hash::sha256(input) +} diff --git a/test_programs/compilation_report.sh b/test_programs/compilation_report.sh new file mode 100755 index 00000000000..786dbd75fe8 --- /dev/null +++ b/test_programs/compilation_report.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +set -e + +PARSE_TIME=$(realpath "$(dirname "$0")/parse_time.sh") +current_dir=$(pwd) +base_path="$current_dir/execution_success" + +# Tests to be profiled for compilation report +tests_to_profile=("sha256_regression" "regression_4709" "ram_blowup_regression") + +echo "{\"compilation_reports\": [ " > $current_dir/compilation_report.json + +# If there is an argument that means we want to generate a report for only the current directory +if [ "$1" == "1" ]; then + base_path="$current_dir" + tests_to_profile=(".") +fi + +ITER="1" +NUM_ARTIFACTS=${#tests_to_profile[@]} +FLAGS=${FLAGS:- ""} + +for dir in ${tests_to_profile[@]}; do + if [[ " ${excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + if [[ ${CI-false} = "true" ]] && [[ " ${ci_excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + cd $base_path/$dir + + # The default package to run is the supplied list hardcoded at the top of the script + PACKAGE_NAME=$dir + # Otherwise default to the current directory as the package we want to run + if [ "$1" == "1" ]; then + PACKAGE_NAME=$(basename $current_dir) + fi + + NUM_RUNS=$2 + TOTAL_TIME=0 + + for ((i = 1; i <= NUM_RUNS; i++)); do + NOIR_LOG=trace NARGO_LOG_DIR=./tmp nargo compile --force --silence-warnings $FLAGS + done + + TIMES=($(jq -r '. | select(.target == "nargo::cli" and .fields.message == "close") | .fields."time.busy"' ./tmp/*)) + + AVG_TIME=$(awk -v RS=" " -v parse_time="$PARSE_TIME" ' + { + # Times are formatted annoyingly so we need to parse it. + parse_time" "$1 | getline current_time + close(parse_time" "$1) + sum += current_time; + n++; + } + END { + if (n > 0) + printf "%.3f\n", sum / n + else + printf "%.3f\n", 0 + }' <<<"${TIMES[@]}") + + jq -rc "{artifact_name: \"$PACKAGE_NAME\", time: \""$AVG_TIME"s\"}" --null-input >> $current_dir/compilation_report.json + + if (($ITER != $NUM_ARTIFACTS)); then + echo "," >> $current_dir/compilation_report.json + fi + + rm -rf ./tmp + + ITER=$(( $ITER + 1 )) +done + +echo "]}" >> $current_dir/compilation_report.json diff --git a/test_programs/compile_failure/arithmetic_generics_intermediate_underflow/Nargo.toml b/test_programs/compile_failure/arithmetic_generics_intermediate_underflow/Nargo.toml new file mode 100644 index 00000000000..0c5d98628a1 --- /dev/null +++ b/test_programs/compile_failure/arithmetic_generics_intermediate_underflow/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "arithmetic_generics_intermediate_underflow" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/arithmetic_generics_intermediate_underflow/src/main.nr b/test_programs/compile_failure/arithmetic_generics_intermediate_underflow/src/main.nr new file mode 100644 index 00000000000..df778468397 --- /dev/null +++ b/test_programs/compile_failure/arithmetic_generics_intermediate_underflow/src/main.nr @@ -0,0 +1,32 @@ +// docs:start:intermediate-underflow-example +fn main() { + // From main it looks like there's nothing sketchy going on + seems_fine([]); +} + +// Since `seems_fine` says it can receive and return any length N +fn seems_fine(array: [Field; N]) -> [Field; N] { + // But inside `seems_fine` we pop from the array which + // requires the length to be greater than zero. + + // error: Could not determine array length `(0 - 1)` + push_zero(pop(array)) +} + +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn push_zero(array: [Field; N]) -> [Field; N + 1] { + let mut result: [Field; N + 1] = std::mem::zeroed(); + for i in 0..N { + result[i] = array[i]; + } + // index N is already zeroed + result +} +// docs:end:intermediate-underflow-example diff --git a/test_programs/compile_failure/arithmetic_generics_underflow/Nargo.toml b/test_programs/compile_failure/arithmetic_generics_underflow/Nargo.toml new file mode 100644 index 00000000000..f024f4c3b59 --- /dev/null +++ b/test_programs/compile_failure/arithmetic_generics_underflow/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "arithmetic_generics_underflow" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/arithmetic_generics_underflow/src/main.nr b/test_programs/compile_failure/arithmetic_generics_underflow/src/main.nr new file mode 100644 index 00000000000..bc670a75a76 --- /dev/null +++ b/test_programs/compile_failure/arithmetic_generics_underflow/src/main.nr @@ -0,0 +1,14 @@ +// docs:start:underflow-example +fn pop(array: [Field; N]) -> [Field; N - 1] { + let mut result: [Field; N - 1] = std::mem::zeroed(); + for i in 0..N - 1 { + result[i] = array[i]; + } + result +} + +fn main() { + // error: Could not determine array length `(0 - 1)` + pop([]); +} +// docs:end:underflow-example 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..16902860a16 --- /dev/null +++ b/test_programs/compile_failure/array_length_defaulting/src/main.nr @@ -0,0 +1,10 @@ +fn main() { + let x = std::mem::zeroed(); + foo(x); +} + +fn foo(array: [Field; N]) { + for elem in array { + println(elem); + } +} diff --git a/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml b/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml new file mode 100644 index 00000000000..6171770b62b --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_array" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr b/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr new file mode 100644 index 00000000000..43da3ef0eaa --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant([dynamic_one]); +} diff --git a/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml b/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml new file mode 100644 index 00000000000..e5583e53126 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_plus" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr b/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr new file mode 100644 index 00000000000..f8a377092a2 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant(dynamic_one + 1 == 3); +} diff --git a/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml b/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml new file mode 100644 index 00000000000..d1d068a79b8 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr b/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr new file mode 100644 index 00000000000..f07002d7d4c --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant(&[dynamic_one]); +} diff --git a/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml b/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml new file mode 100644 index 00000000000..18781f4d57d --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_struct_array" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr b/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr new file mode 100644 index 00000000000..b9f4dceafc0 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 +) { + let foo_dynamic_array = Foo { field: 0, array: [dynamic_one, 2, 3], slice: &[] }; + assert_constant(foo_dynamic_array); +} diff --git a/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml b/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml new file mode 100644 index 00000000000..173ea44101a --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_struct_field" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr b/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr new file mode 100644 index 00000000000..e7986c93b6b --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 +) { + let foo_dynamic = Foo { field: dynamic_one, array: [1, 2, 3], slice: &[] }; + assert_constant(foo_dynamic); +} diff --git a/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml b/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml new file mode 100644 index 00000000000..426f4826a0b --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_struct_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr b/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr new file mode 100644 index 00000000000..c775b563928 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 +) { + let foo_dynamic_slice = Foo { field: 0, array: [1, 2, 3], slice: &[dynamic_one] }; + assert_constant(foo_dynamic_slice); +} diff --git a/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml b/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml new file mode 100644 index 00000000000..de7b2031300 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_tuple" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr b/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr new file mode 100644 index 00000000000..579a5a0991f --- /dev/null +++ b/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant((dynamic_one, 2)); +} diff --git a/test_programs/compile_failure/assert_constant_fail/Nargo.toml b/test_programs/compile_failure/assert_constant_fail/Nargo.toml new file mode 100644 index 00000000000..2eaf67246e1 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_fail/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "assert_constant_fail" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/assert_constant_fail/src/main.nr b/test_programs/compile_failure/assert_constant_fail/src/main.nr new file mode 100644 index 00000000000..b8d5d255228 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_fail/src/main.nr @@ -0,0 +1,10 @@ +use std::assert_constant; + +fn main(x: Field) { + foo(5, x); +} + +fn foo(constant: Field, non_constant: Field) { + assert_constant(constant); + assert_constant(non_constant); +} diff --git a/test_programs/compile_failure/assert_constant_false/Nargo.toml b/test_programs/compile_failure/assert_constant_false/Nargo.toml new file mode 100644 index 00000000000..cb8d59f4293 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_false/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_false" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/assert_constant_false/src/main.nr b/test_programs/compile_failure/assert_constant_false/src/main.nr new file mode 100644 index 00000000000..f4e98cfec37 --- /dev/null +++ b/test_programs/compile_failure/assert_constant_false/src/main.nr @@ -0,0 +1,3 @@ +fn main() { + std::static_assert(false, ""); +} diff --git a/test_programs/compile_failure/assert_eq_struct/Nargo.toml b/test_programs/compile_failure/assert_eq_struct/Nargo.toml new file mode 100644 index 00000000000..9fcdcc10bb7 --- /dev/null +++ b/test_programs/compile_failure/assert_eq_struct/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "assert_eq_struct" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_failure/assert_eq_struct/src/main.nr b/test_programs/compile_failure/assert_eq_struct/src/main.nr new file mode 100644 index 00000000000..54b937e5f1d --- /dev/null +++ b/test_programs/compile_failure/assert_eq_struct/src/main.nr @@ -0,0 +1,5 @@ +struct myStruct {} +// `assert_eq` should not allow asserting equality between types for which `==` is not defined. +fn main(x: myStruct, y: pub myStruct) { + assert_eq(x, y); +} diff --git a/test_programs/compile_failure/brillig_mut_ref_from_acir/Nargo.toml b/test_programs/compile_failure/brillig_mut_ref_from_acir/Nargo.toml new file mode 100644 index 00000000000..a20ee09714c --- /dev/null +++ b/test_programs/compile_failure/brillig_mut_ref_from_acir/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_mut_ref_from_acir" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file 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 new file mode 100644 index 00000000000..d4450ec62b1 --- /dev/null +++ b/test_programs/compile_failure/brillig_mut_ref_from_acir/src/main.nr @@ -0,0 +1,9 @@ +unconstrained fn mut_ref_identity(value: &mut Field) -> Field { + *value +} + +fn main(mut x: Field, y: pub Field) { + /// Safety: testing context + let returned_x = unsafe { mut_ref_identity(&mut x) }; + assert(returned_x == x); +} diff --git a/test_programs/compile_failure/brillig_nested_slices/Nargo.toml b/test_programs/compile_failure/brillig_nested_slices/Nargo.toml new file mode 100644 index 00000000000..d84338cdbb4 --- /dev/null +++ b/test_programs/compile_failure/brillig_nested_slices/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "brillig_nested_slices" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_failure/brillig_nested_slices/src/main.nr b/test_programs/compile_failure/brillig_nested_slices/src/main.nr new file mode 100644 index 00000000000..ee61195cf8f --- /dev/null +++ b/test_programs/compile_failure/brillig_nested_slices/src/main.nr @@ -0,0 +1,72 @@ +use std::slice; +// Tests nested slice passing to/from functions +unconstrained fn push_back_to_slice(slice: [T], item: T) -> [T] { + slice.push_back(item) +} + +struct NestedSliceStruct { + id: Field, + arr: [Field] +} + +unconstrained fn create_foo(id: Field, value: Field) -> NestedSliceStruct { + let mut arr = [id]; + arr = arr.push_back(value); + NestedSliceStruct { id, arr } +} + +unconstrained fn main(a: Field, b: Field) { + let mut slice = [create_foo(a, b), create_foo(b, a)]; + assert(slice.len() == 2); + + assert(slice[0].id == a); + assert(slice[0].arr[0] == a); + assert(slice[1].id == b); + assert(slice[1].arr[1] == a); + + slice = push_back_to_slice(slice, create_foo(0, 42)); + assert(slice.len() == 3); + + assert(slice[0].id == a); + assert(slice[0].arr[0] == a); + assert(slice[1].id == b); + assert(slice[1].arr[1] == a); + + assert(slice[2].id == 0); + assert(slice[2].arr[0] == 0); + assert(slice[2].arr[1] == 42); + + slice = slice.push_front(create_foo(1, 43)); + slice = slice.push_back(create_foo(2, 44)); + + assert(slice.len() == 5); + + let pop_front_result = slice.pop_front(); + slice = pop_front_result.1; + assert(pop_front_result.0.id == 1); + + let pop_back_result = slice.pop_back(); + slice = pop_back_result.0; + assert(pop_back_result.1.id == 2); + + assert(slice.len() == 3); + + let mut remove_result = slice.remove(0); + slice = remove_result.0; + let mut removed_item = remove_result.1; + assert(removed_item.arr[0] == a); + + remove_result = slice.remove(1); + slice = remove_result.0; + removed_item = remove_result.1; + assert(removed_item.arr[0] == 0); + + let last_item = slice[0]; + + assert(last_item.id == b); + slice = slice.insert(1, removed_item); + + assert(slice.len() == 2); + assert(slice[0].id == b); + assert(slice[1].id == 0); +} diff --git a/test_programs/compile_failure/brillig_slice_to_acir/Nargo.toml b/test_programs/compile_failure/brillig_slice_to_acir/Nargo.toml new file mode 100644 index 00000000000..c3e51561cc7 --- /dev/null +++ b/test_programs/compile_failure/brillig_slice_to_acir/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_slice_to_acir" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/brillig_slice_to_acir/src/main.nr b/test_programs/compile_failure/brillig_slice_to_acir/src/main.nr new file mode 100644 index 00000000000..dcf23aac5f5 --- /dev/null +++ b/test_programs/compile_failure/brillig_slice_to_acir/src/main.nr @@ -0,0 +1,14 @@ +global DEPTH: Field = 40000; + +fn main(x: [u32; DEPTH], y: u32) { + let mut new_x = []; + new_x = clear(x, y); +} + +unconstrained fn clear(x: [u32; DEPTH], y: u32) -> [u32] { + let mut a = []; + for i in 0..y { + a = a.push_back(x[i]); + } + a +} diff --git a/test_programs/compile_failure/brillig_vec_to_acir/Nargo.toml b/test_programs/compile_failure/brillig_vec_to_acir/Nargo.toml new file mode 100644 index 00000000000..c09fc417b55 --- /dev/null +++ b/test_programs/compile_failure/brillig_vec_to_acir/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_vec_to_acir" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/brillig_vec_to_acir/src/main.nr b/test_programs/compile_failure/brillig_vec_to_acir/src/main.nr new file mode 100644 index 00000000000..8f872f1b903 --- /dev/null +++ b/test_programs/compile_failure/brillig_vec_to_acir/src/main.nr @@ -0,0 +1,14 @@ +global DEPTH: Field = 40000; + +fn main(x: [u32; DEPTH], y: u32) { + let mut new_x = Vec::new(); + new_x = clear(x, y); +} + +unconstrained fn clear(x: [u32; DEPTH], y: u32) -> Vec { + let mut a = Vec::new(); + for i in 0..y { + a.push(x[i]); + } + a +} diff --git a/test_programs/compile_failure/builtin_function_declaration/Nargo.toml b/test_programs/compile_failure/builtin_function_declaration/Nargo.toml new file mode 100644 index 00000000000..80312a7aec1 --- /dev/null +++ b/test_programs/compile_failure/builtin_function_declaration/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "builtin_function_declaration" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/builtin_function_declaration/src/main.nr b/test_programs/compile_failure/builtin_function_declaration/src/main.nr new file mode 100644 index 00000000000..1f0af24a243 --- /dev/null +++ b/test_programs/compile_failure/builtin_function_declaration/src/main.nr @@ -0,0 +1,10 @@ +// This test prevents users from trying to create their own builtin functions as these should only exist in the stdlib. + +// This would otherwise be a perfectly valid declaration of the `to_le_bits` builtin function +#[builtin(to_le_bits)] +fn to_le_bits(_x: Field) -> [u1: N] {} + +fn main(x: Field) -> pub u1 { + let bits: [u1; 100] = to_le_bits(x); + bits[0] +} diff --git a/test_programs/compile_failure/cannot_deduce_numeric_generic/Nargo.toml b/test_programs/compile_failure/cannot_deduce_numeric_generic/Nargo.toml new file mode 100644 index 00000000000..e87c464f6c7 --- /dev/null +++ b/test_programs/compile_failure/cannot_deduce_numeric_generic/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cannot_deduce_numeric_generic" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_failure/cannot_deduce_numeric_generic/src/main.nr b/test_programs/compile_failure/cannot_deduce_numeric_generic/src/main.nr new file mode 100644 index 00000000000..ee889e805f7 --- /dev/null +++ b/test_programs/compile_failure/cannot_deduce_numeric_generic/src/main.nr @@ -0,0 +1,8 @@ +fn foo() -> u32 { + N +} + +fn main() { + let _ = foo(); +} + diff --git a/test_programs/compile_failure/checked_transmute/Nargo.toml b/test_programs/compile_failure/checked_transmute/Nargo.toml new file mode 100644 index 00000000000..9d01c873b03 --- /dev/null +++ b/test_programs/compile_failure/checked_transmute/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "checked_transmute" +type = "bin" +authors = [""] +compiler_version = ">=0.35.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/checked_transmute/src/main.nr b/test_programs/compile_failure/checked_transmute/src/main.nr new file mode 100644 index 00000000000..058fa0ec911 --- /dev/null +++ b/test_programs/compile_failure/checked_transmute/src/main.nr @@ -0,0 +1,9 @@ +use std::mem::checked_transmute; + +fn main() { + let _: [Field; 2] = transmute_fail([1]); +} + +pub fn transmute_fail(x: [Field; N]) -> [Field; N + 1] { + checked_transmute(x) +} diff --git a/test_programs/compile_failure/comptime_apply_failing_range_constraint/Nargo.toml b/test_programs/compile_failure/comptime_apply_failing_range_constraint/Nargo.toml new file mode 100644 index 00000000000..e14cfeae5d6 --- /dev/null +++ b/test_programs/compile_failure/comptime_apply_failing_range_constraint/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "comptime_apply_failing_range_constraint" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_failure/comptime_apply_failing_range_constraint/src/main.nr b/test_programs/compile_failure/comptime_apply_failing_range_constraint/src/main.nr new file mode 100644 index 00000000000..752f13a2e51 --- /dev/null +++ b/test_programs/compile_failure/comptime_apply_failing_range_constraint/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + comptime { + 256.assert_max_bit_size::<8>() + } +} diff --git a/test_programs/compile_failure/comptime_parse_all_tokens/Nargo.toml b/test_programs/compile_failure/comptime_parse_all_tokens/Nargo.toml new file mode 100644 index 00000000000..2d9b78c9c38 --- /dev/null +++ b/test_programs/compile_failure/comptime_parse_all_tokens/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_parse_all_tokens" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/test_programs/compile_failure/comptime_parse_all_tokens/src/main.nr b/test_programs/compile_failure/comptime_parse_all_tokens/src/main.nr new file mode 100644 index 00000000000..8e9a607f44a --- /dev/null +++ b/test_programs/compile_failure/comptime_parse_all_tokens/src/main.nr @@ -0,0 +1,9 @@ +#[foo] +fn main() {} + +comptime fn foo(_f: FunctionDefinition) -> Quoted { + let t = quote { Field }.as_type(); + // We parse 0 or more top level expressions from attribute output + // so for invalid input we previously "successfully" parsed 0 items. + quote { use $t; } +} diff --git a/test_programs/compile_failure/comptime_var_not_defined/Nargo.toml b/test_programs/compile_failure/comptime_var_not_defined/Nargo.toml new file mode 100644 index 00000000000..f2604ee0692 --- /dev/null +++ b/test_programs/compile_failure/comptime_var_not_defined/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_var_not_defined" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/compile_failure/comptime_var_not_defined/src/main.nr b/test_programs/compile_failure/comptime_var_not_defined/src/main.nr new file mode 100644 index 00000000000..ab4ea69e96c --- /dev/null +++ b/test_programs/compile_failure/comptime_var_not_defined/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + comptime { + foo(); + } +} diff --git a/test_programs/compile_failure/constrain_typo/Nargo.toml b/test_programs/compile_failure/constrain_typo/Nargo.toml new file mode 100644 index 00000000000..191121e59b7 --- /dev/null +++ b/test_programs/compile_failure/constrain_typo/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "constrain_typo" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_failure/constrain_typo/src/main.nr b/test_programs/compile_failure/constrain_typo/src/main.nr new file mode 100644 index 00000000000..ee99663da46 --- /dev/null +++ b/test_programs/compile_failure/constrain_typo/src/main.nr @@ -0,0 +1,7 @@ + +// This should not compile as the keyword +// is `constrain` and not `constrai` + +fn main(x : Field, y : Field) { + constrai x != y; +} \ No newline at end of file diff --git a/test_programs/compile_failure/custom_entry_not_found/Nargo.toml b/test_programs/compile_failure/custom_entry_not_found/Nargo.toml new file mode 100644 index 00000000000..a32696d3370 --- /dev/null +++ b/test_programs/compile_failure/custom_entry_not_found/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "custom_entry" +type = "bin" +# Testing that this file is missing and doesn't fallback to default `main.nr` file +entry = "src/foobarbaz.nr" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_failure/custom_entry_not_found/src/main.nr b/test_programs/compile_failure/custom_entry_not_found/src/main.nr new file mode 100644 index 00000000000..00e94414c0b --- /dev/null +++ b/test_programs/compile_failure/custom_entry_not_found/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field) { + assert(x == 1); +} diff --git a/test_programs/compile_failure/cyclic_dep/Nargo.toml b/test_programs/compile_failure/cyclic_dep/Nargo.toml new file mode 100644 index 00000000000..6a5a9b7db73 --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cyclic_dep" +type = "bin" +authors = [""] + +[dependencies] +dep1 = { path= "./dep1"} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/dep1/Nargo.toml b/test_programs/compile_failure/cyclic_dep/dep1/Nargo.toml new file mode 100644 index 00000000000..4782bbd5cda --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/dep1/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "dep1" +type = "lib" +authors = [""] + +[dependencies] +dep1 = { path= "../dep2"} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/dep1/src/lib.nr b/test_programs/compile_failure/cyclic_dep/dep1/src/lib.nr new file mode 100644 index 00000000000..02b68c56bd2 --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/dep1/src/lib.nr @@ -0,0 +1,3 @@ +fn bar() { + +} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/dep2/Nargo.toml b/test_programs/compile_failure/cyclic_dep/dep2/Nargo.toml new file mode 100644 index 00000000000..5e2a0f304b0 --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/dep2/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "dep2" +type = "lib" +authors = [""] + +[dependencies] +dep1 = { path= "../dep1"} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/dep2/src/lib.nr b/test_programs/compile_failure/cyclic_dep/dep2/src/lib.nr new file mode 100644 index 00000000000..298a0f3c7ca --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/dep2/src/lib.nr @@ -0,0 +1,3 @@ +fn foo() { + +} \ No newline at end of file diff --git a/test_programs/compile_failure/cyclic_dep/src/main.nr b/test_programs/compile_failure/cyclic_dep/src/main.nr new file mode 100644 index 00000000000..c55ca748334 --- /dev/null +++ b/test_programs/compile_failure/cyclic_dep/src/main.nr @@ -0,0 +1,7 @@ +use dep1::foo; +use dep2::bar; + +fn main() { + dep1::foo(); + dep2::bar(); +} diff --git a/test_programs/compile_failure/dep_impl_primitive/Nargo.toml b/test_programs/compile_failure/dep_impl_primitive/Nargo.toml new file mode 100644 index 00000000000..afe5a5134ca --- /dev/null +++ b/test_programs/compile_failure/dep_impl_primitive/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "dep_impl_primitive" +type = "bin" +authors = [""] +[dependencies] +bad_impl = { path = "../../test_libraries/bad_impl" } diff --git a/test_programs/compile_failure/dep_impl_primitive/src/main.nr b/test_programs/compile_failure/dep_impl_primitive/src/main.nr new file mode 100644 index 00000000000..40578574c75 --- /dev/null +++ b/test_programs/compile_failure/dep_impl_primitive/src/main.nr @@ -0,0 +1,5 @@ +use bad_impl; + +fn main(x: Field) { + x.something(); +} diff --git a/test_programs/compile_failure/dep_submodule_overlap/Nargo.toml b/test_programs/compile_failure/dep_submodule_overlap/Nargo.toml new file mode 100644 index 00000000000..0d5a6221ef2 --- /dev/null +++ b/test_programs/compile_failure/dep_submodule_overlap/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "dep_submodule_overlap" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] +reexporting_lib = { path = "../../test_libraries/reexporting_lib" } diff --git a/test_programs/compile_failure/dep_submodule_overlap/src/lib.nr b/test_programs/compile_failure/dep_submodule_overlap/src/lib.nr new file mode 100644 index 00000000000..e2e82b2f5cd --- /dev/null +++ b/test_programs/compile_failure/dep_submodule_overlap/src/lib.nr @@ -0,0 +1,3 @@ +struct MyStruct { + inner: Field +} diff --git a/test_programs/compile_failure/dep_submodule_overlap/src/main.nr b/test_programs/compile_failure/dep_submodule_overlap/src/main.nr new file mode 100644 index 00000000000..c53630c53ca --- /dev/null +++ b/test_programs/compile_failure/dep_submodule_overlap/src/main.nr @@ -0,0 +1,9 @@ +use reexporting_lib::{MyStruct, lib}; + +mod lib; +use crate::lib::MyStruct; + +fn main() { + let x = MyStruct { inner: 0 }; + assert(lib::is_struct_zero(x)); +} diff --git a/test_programs/compile_failure/depend_on_bin/Nargo.toml b/test_programs/compile_failure/depend_on_bin/Nargo.toml new file mode 100644 index 00000000000..8334a38eb4b --- /dev/null +++ b/test_programs/compile_failure/depend_on_bin/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "depend_on_bin" +type = "bin" +authors = [""] +[dependencies] +bin_dep = { path = "../../test_libraries/bin_dep" } diff --git a/test_programs/compile_failure/depend_on_bin/src/main.nr b/test_programs/compile_failure/depend_on_bin/src/main.nr new file mode 100644 index 00000000000..d7aff600fe6 --- /dev/null +++ b/test_programs/compile_failure/depend_on_bin/src/main.nr @@ -0,0 +1,5 @@ +use bin_dep; + +fn main(x : Field) { + assert(x == 1); +} diff --git a/test_programs/compile_failure/dup_trait_implementation_4/Nargo.toml b/test_programs/compile_failure/dup_trait_implementation_4/Nargo.toml new file mode 100644 index 00000000000..18352cb34b5 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_4/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "dup_trait_implementation_4" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/dup_trait_implementation_4/src/main.nr b/test_programs/compile_failure/dup_trait_implementation_4/src/main.nr new file mode 100644 index 00000000000..e03fe8b3eeb --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_4/src/main.nr @@ -0,0 +1,5 @@ +mod module1; +mod module2; +mod module3; + +fn main() {} diff --git a/test_programs/compile_failure/dup_trait_implementation_4/src/module1.nr b/test_programs/compile_failure/dup_trait_implementation_4/src/module1.nr new file mode 100644 index 00000000000..4d41ff2909a --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_4/src/module1.nr @@ -0,0 +1,2 @@ +trait MyTrait { +} diff --git a/test_programs/compile_failure/dup_trait_implementation_4/src/module2.nr b/test_programs/compile_failure/dup_trait_implementation_4/src/module2.nr new file mode 100644 index 00000000000..3cadb6d78cb --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_4/src/module2.nr @@ -0,0 +1,2 @@ +struct MyStruct { +} diff --git a/test_programs/compile_failure/dup_trait_implementation_4/src/module3.nr b/test_programs/compile_failure/dup_trait_implementation_4/src/module3.nr new file mode 100644 index 00000000000..17874893190 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_4/src/module3.nr @@ -0,0 +1,6 @@ +use crate::module1::MyTrait; +use crate::module2::MyStruct; +// those are not the same 'Path', but they refer to the same trait & impl +// so a Duplicate error should be thrown +impl MyTrait for MyStruct {} +impl crate::module1::MyTrait for crate::module2::MyStruct { } diff --git a/test_programs/compile_failure/dup_trait_implementation_5/Nargo.toml b/test_programs/compile_failure/dup_trait_implementation_5/Nargo.toml new file mode 100644 index 00000000000..40b7c3d0269 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_5/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "dup_trait_implementation_5" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/dup_trait_implementation_5/src/main.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/main.nr new file mode 100644 index 00000000000..b5719009898 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_5/src/main.nr @@ -0,0 +1,6 @@ +mod module1; +mod module2; +mod module3; +mod module4; + +fn main() {} diff --git a/test_programs/compile_failure/dup_trait_implementation_5/src/module1.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/module1.nr new file mode 100644 index 00000000000..4d41ff2909a --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_5/src/module1.nr @@ -0,0 +1,2 @@ +trait MyTrait { +} diff --git a/test_programs/compile_failure/dup_trait_implementation_5/src/module2.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/module2.nr new file mode 100644 index 00000000000..3cadb6d78cb --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_5/src/module2.nr @@ -0,0 +1,2 @@ +struct MyStruct { +} diff --git a/test_programs/compile_failure/dup_trait_implementation_5/src/module3.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/module3.nr new file mode 100644 index 00000000000..ac886d441cd --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_5/src/module3.nr @@ -0,0 +1,4 @@ +use crate::module1::MyTrait; +use crate::module2::MyStruct; + +impl MyTrait for MyStruct {} diff --git a/test_programs/compile_failure/dup_trait_implementation_5/src/module4.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/module4.nr new file mode 100644 index 00000000000..dfa660f80b1 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_implementation_5/src/module4.nr @@ -0,0 +1,3 @@ +// another module in the crate implements the same trait + struct +// a Duplicate error should be thrown +impl crate::module1::MyTrait for crate::module2::MyStruct { } diff --git a/test_programs/compile_failure/dup_trait_items_1/Nargo.toml b/test_programs/compile_failure/dup_trait_items_1/Nargo.toml new file mode 100644 index 00000000000..078a336c282 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_1/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "dup_trait_items_1" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/dup_trait_items_1/src/main.nr b/test_programs/compile_failure/dup_trait_items_1/src/main.nr new file mode 100644 index 00000000000..863139333f7 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_1/src/main.nr @@ -0,0 +1,6 @@ +trait MyTrait { + fn SomeFunc(); + fn SomeFunc(); +} + +fn main() {} diff --git a/test_programs/compile_failure/dup_trait_items_2/Nargo.toml b/test_programs/compile_failure/dup_trait_items_2/Nargo.toml new file mode 100644 index 00000000000..41e1a3b3fd9 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_2/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "dup_trait_items_2" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/dup_trait_items_2/src/main.nr b/test_programs/compile_failure/dup_trait_items_2/src/main.nr new file mode 100644 index 00000000000..cdcac745208 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_2/src/main.nr @@ -0,0 +1,6 @@ +trait MyTrait { + let SomeConst: u32; + let SomeConst: Field; +} + +fn main() {} diff --git a/test_programs/compile_failure/dup_trait_items_3/Nargo.toml b/test_programs/compile_failure/dup_trait_items_3/Nargo.toml new file mode 100644 index 00000000000..1388f3c83ee --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_3/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "dup_trait_items_3" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/dup_trait_items_3/src/main.nr b/test_programs/compile_failure/dup_trait_items_3/src/main.nr new file mode 100644 index 00000000000..f6ed35468b9 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_3/src/main.nr @@ -0,0 +1,6 @@ +trait MyTrait { + type SomeType; + type SomeType; +} + +fn main() {} diff --git a/test_programs/compile_failure/dup_trait_items_4/Nargo.toml b/test_programs/compile_failure/dup_trait_items_4/Nargo.toml new file mode 100644 index 00000000000..43e8096548b --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_4/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "dup_trait_items_4" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/dup_trait_items_4/src/main.nr b/test_programs/compile_failure/dup_trait_items_4/src/main.nr new file mode 100644 index 00000000000..fc0a7011a5d --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_4/src/main.nr @@ -0,0 +1,6 @@ +trait MyTrait { + let MyItem: u32; + fn MyItem(); +} + +fn main() {} diff --git a/test_programs/compile_failure/dup_trait_items_5/Nargo.toml b/test_programs/compile_failure/dup_trait_items_5/Nargo.toml new file mode 100644 index 00000000000..0af8ef88cea --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_5/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "dup_trait_items_5" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/dup_trait_items_5/src/main.nr b/test_programs/compile_failure/dup_trait_items_5/src/main.nr new file mode 100644 index 00000000000..da42d27ac36 --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_5/src/main.nr @@ -0,0 +1,6 @@ +trait MyTrait { + fn MyItem(); + let MyItem: u32; +} + +fn main() {} diff --git a/test_programs/compile_failure/dup_trait_items_6/Nargo.toml b/test_programs/compile_failure/dup_trait_items_6/Nargo.toml new file mode 100644 index 00000000000..dd5f13438ec --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_6/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "dup_trait_items_6" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/dup_trait_items_6/src/main.nr b/test_programs/compile_failure/dup_trait_items_6/src/main.nr new file mode 100644 index 00000000000..a1a731d943b --- /dev/null +++ b/test_programs/compile_failure/dup_trait_items_6/src/main.nr @@ -0,0 +1,15 @@ +trait MyTrait { + fn SomeFunc() { }; + fn SomeFunc() { }; +} + +struct MyStruct { +} + +impl MyTrait for MyStruct { + fn SomeFunc() { + } +} + +fn main() { +} diff --git a/test_programs/compile_failure/duplicate_declaration/Nargo.toml b/test_programs/compile_failure/duplicate_declaration/Nargo.toml new file mode 100644 index 00000000000..a4c82c70642 --- /dev/null +++ b/test_programs/compile_failure/duplicate_declaration/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "duplicate_declaration" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_failure/duplicate_declaration/src/main.nr b/test_programs/compile_failure/duplicate_declaration/src/main.nr new file mode 100644 index 00000000000..e4433ef4078 --- /dev/null +++ b/test_programs/compile_failure/duplicate_declaration/src/main.nr @@ -0,0 +1,8 @@ +// Duplicate functions should not compile +fn hello(x: Field) -> Field { + x +} + +fn hello(x: Field) -> Field { + x +} diff --git a/test_programs/compile_failure/field_modulo/Nargo.toml b/test_programs/compile_failure/field_modulo/Nargo.toml new file mode 100644 index 00000000000..94934f13e56 --- /dev/null +++ b/test_programs/compile_failure/field_modulo/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "field_modulo" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/field_modulo/src/main.nr b/test_programs/compile_failure/field_modulo/src/main.nr new file mode 100644 index 00000000000..a482b68806b --- /dev/null +++ b/test_programs/compile_failure/field_modulo/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field) -> pub Field { + x % 2 +} diff --git a/test_programs/compile_failure/foreign_function_declaration/Nargo.toml b/test_programs/compile_failure/foreign_function_declaration/Nargo.toml new file mode 100644 index 00000000000..951658d7fb8 --- /dev/null +++ b/test_programs/compile_failure/foreign_function_declaration/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "foreign_function_declaration" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/compile_failure/foreign_function_declaration/src/main.nr b/test_programs/compile_failure/foreign_function_declaration/src/main.nr new file mode 100644 index 00000000000..6273067f6a7 --- /dev/null +++ b/test_programs/compile_failure/foreign_function_declaration/src/main.nr @@ -0,0 +1,10 @@ +// This test prevents users from trying to create their own blackbox functions as these should only exist in the stdlib. + +// This would otherwise be a perfectly valid definition of the `pedersen_hash` black box function, +// however executing the circuit results in an unhelpful ICE. +#[foreign(pedersen_hash)] +fn my_pedersen_hash(_input: [Field; N]) -> Field {} + +fn main() -> pub Field { + my_pedersen_hash([1]) +} diff --git a/test_programs/compile_failure/global_without_a_type_used_as_array_length/Nargo.toml b/test_programs/compile_failure/global_without_a_type_used_as_array_length/Nargo.toml new file mode 100644 index 00000000000..b2c83a26988 --- /dev/null +++ b/test_programs/compile_failure/global_without_a_type_used_as_array_length/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "global_without_a_type_used_as_array_length" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/global_without_a_type_used_as_array_length/src/main.nr b/test_programs/compile_failure/global_without_a_type_used_as_array_length/src/main.nr new file mode 100644 index 00000000000..9edda231dec --- /dev/null +++ b/test_programs/compile_failure/global_without_a_type_used_as_array_length/src/main.nr @@ -0,0 +1,2 @@ +global BAR = OOPS; +global X: [Field; BAR] = []; diff --git a/test_programs/compile_failure/integer_too_large/Nargo.toml b/test_programs/compile_failure/integer_too_large/Nargo.toml new file mode 100644 index 00000000000..08439d2f02e --- /dev/null +++ b/test_programs/compile_failure/integer_too_large/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "integer_too_large" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/integer_too_large/src/main.nr b/test_programs/compile_failure/integer_too_large/src/main.nr new file mode 100644 index 00000000000..a8a2c383fe6 --- /dev/null +++ b/test_programs/compile_failure/integer_too_large/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: Field) { + let too_large: Field = 233149999999999999999999999999999999999999999999999999999999923314999999999999999999999999999999999999999999999999999999999923314999999999999999999999999999999999999999999999999999999999; + assert(x == too_large); +} \ No newline at end of file diff --git a/test_programs/compile_failure/invalid_dependency_name/Nargo.toml b/test_programs/compile_failure/invalid_dependency_name/Nargo.toml new file mode 100644 index 00000000000..99d184acdcf --- /dev/null +++ b/test_programs/compile_failure/invalid_dependency_name/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "invalid_dependency_name" +type = "bin" +authors = [""] +[dependencies] +bad_name = { path = "../../test_libraries/bad_name" } diff --git a/test_programs/compile_failure/invalid_dependency_name/src/main.nr b/test_programs/compile_failure/invalid_dependency_name/src/main.nr new file mode 100644 index 00000000000..faf1ba0045a --- /dev/null +++ b/test_programs/compile_failure/invalid_dependency_name/src/main.nr @@ -0,0 +1 @@ +fn main(x: Field) { } diff --git a/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml b/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml new file mode 100644 index 00000000000..12776f47712 --- /dev/null +++ b/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "invalid_main_sub_lib" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/invalid_main_sub_lib/src/main.nr b/test_programs/compile_failure/invalid_main_sub_lib/src/main.nr new file mode 100644 index 00000000000..4658900a47a --- /dev/null +++ b/test_programs/compile_failure/invalid_main_sub_lib/src/main.nr @@ -0,0 +1,5 @@ +mod lib; + +use crate::lib::foo; + +fn main() {} diff --git a/test_programs/compile_failure/invalid_main_sub_lib/src/main/lib.nr b/test_programs/compile_failure/invalid_main_sub_lib/src/main/lib.nr new file mode 100644 index 00000000000..0f89316b5bd --- /dev/null +++ b/test_programs/compile_failure/invalid_main_sub_lib/src/main/lib.nr @@ -0,0 +1,3 @@ +pub fn foo() -> bool { + true +} diff --git a/test_programs/compile_failure/invalid_mod_mod_path/Nargo.toml b/test_programs/compile_failure/invalid_mod_mod_path/Nargo.toml new file mode 100644 index 00000000000..7a93d385c1c --- /dev/null +++ b/test_programs/compile_failure/invalid_mod_mod_path/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "invalid_mod_mod_path" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/invalid_mod_mod_path/main/lib.nr b/test_programs/compile_failure/invalid_mod_mod_path/main/lib.nr new file mode 100644 index 00000000000..0f89316b5bd --- /dev/null +++ b/test_programs/compile_failure/invalid_mod_mod_path/main/lib.nr @@ -0,0 +1,3 @@ +pub fn foo() -> bool { + true +} diff --git a/test_programs/compile_failure/invalid_mod_mod_path/src/main.nr b/test_programs/compile_failure/invalid_mod_mod_path/src/main.nr new file mode 100644 index 00000000000..86fa197360f --- /dev/null +++ b/test_programs/compile_failure/invalid_mod_mod_path/src/main.nr @@ -0,0 +1,4 @@ +mod crate::mod; + +fn main() { +} diff --git a/test_programs/compile_failure/invalid_mod_mod_path/src/mod.nr b/test_programs/compile_failure/invalid_mod_mod_path/src/mod.nr new file mode 100644 index 00000000000..e2f24cb9226 --- /dev/null +++ b/test_programs/compile_failure/invalid_mod_mod_path/src/mod.nr @@ -0,0 +1,3 @@ +pub foo() -> bool { + true +} diff --git a/test_programs/compile_failure/macro_result_type/Nargo.toml b/test_programs/compile_failure/macro_result_type/Nargo.toml new file mode 100644 index 00000000000..664e405d5fe --- /dev/null +++ b/test_programs/compile_failure/macro_result_type/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "macro_result_type" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/test_programs/compile_failure/macro_result_type/src/main.nr b/test_programs/compile_failure/macro_result_type/src/main.nr new file mode 100644 index 00000000000..4dc97d1d422 --- /dev/null +++ b/test_programs/compile_failure/macro_result_type/src/main.nr @@ -0,0 +1,13 @@ +fn main() { + comptime + { + let signature = "hello".as_ctstring(); + let string = signature.as_quoted_str!(); + let result = half(string); + assert_eq(result, 2); + } +} + +comptime fn half(_s: str) -> u32 { + N / 2 +} diff --git a/test_programs/compile_failure/multiple_primary_attributes_fail/Nargo.toml b/test_programs/compile_failure/multiple_primary_attributes_fail/Nargo.toml new file mode 100644 index 00000000000..9aa843d16dc --- /dev/null +++ b/test_programs/compile_failure/multiple_primary_attributes_fail/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "multiple_primary_attributes_fail" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/multiple_primary_attributes_fail/src/main.nr b/test_programs/compile_failure/multiple_primary_attributes_fail/src/main.nr new file mode 100644 index 00000000000..c8d8b0a1969 --- /dev/null +++ b/test_programs/compile_failure/multiple_primary_attributes_fail/src/main.nr @@ -0,0 +1,6 @@ + +#[oracle(oracleName)] +#[builtin(builtinName)] +fn main(x: Field) -> pub Field { + x + 1 +} \ No newline at end of file diff --git a/test_programs/compile_failure/mutability_regression_2911/Nargo.toml b/test_programs/compile_failure/mutability_regression_2911/Nargo.toml new file mode 100644 index 00000000000..05db8252f3b --- /dev/null +++ b/test_programs/compile_failure/mutability_regression_2911/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "mutability_regression_2911" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_failure/mutability_regression_2911/src/main.nr b/test_programs/compile_failure/mutability_regression_2911/src/main.nr new file mode 100644 index 00000000000..a0d53706f97 --- /dev/null +++ b/test_programs/compile_failure/mutability_regression_2911/src/main.nr @@ -0,0 +1,5 @@ +// Expect 'Variable must be mutable to be assigned to' error +fn main() { + let slice : &mut [Field] = &mut []; + slice = &mut (*slice).push_back(1); +} diff --git a/test_programs/compile_failure/negate_unsigned/Nargo.toml b/test_programs/compile_failure/negate_unsigned/Nargo.toml new file mode 100644 index 00000000000..0b5486024c2 --- /dev/null +++ b/test_programs/compile_failure/negate_unsigned/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "negate_unsigned" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/negate_unsigned/src/main.nr b/test_programs/compile_failure/negate_unsigned/src/main.nr new file mode 100644 index 00000000000..4d3c5abe5a4 --- /dev/null +++ b/test_programs/compile_failure/negate_unsigned/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + let var = -1 as u8; + std::println(var); +} diff --git a/test_programs/compile_failure/nested_slice_declared_type/Nargo.toml b/test_programs/compile_failure/nested_slice_declared_type/Nargo.toml new file mode 100644 index 00000000000..b0ba05135ed --- /dev/null +++ b/test_programs/compile_failure/nested_slice_declared_type/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "nested_slice_declared_type" +type = "bin" +authors = [""] +compiler_version = ">=0.22.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/nested_slice_declared_type/src/main.nr b/test_programs/compile_failure/nested_slice_declared_type/src/main.nr new file mode 100644 index 00000000000..417f9a092e0 --- /dev/null +++ b/test_programs/compile_failure/nested_slice_declared_type/src/main.nr @@ -0,0 +1,6 @@ +fn main(x: Field, y: pub Field) { + assert(x != y); + + let slice: [[Field]] = []; + assert(slice.len() != 10); +} diff --git a/test_programs/compile_failure/nested_slice_literal/Nargo.toml b/test_programs/compile_failure/nested_slice_literal/Nargo.toml new file mode 100644 index 00000000000..db919955de5 --- /dev/null +++ b/test_programs/compile_failure/nested_slice_literal/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "nested_slice_literal" +type = "bin" +authors = [""] +compiler_version = ">=0.22.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/nested_slice_literal/src/main.nr b/test_programs/compile_failure/nested_slice_literal/src/main.nr new file mode 100644 index 00000000000..3140818d0b2 --- /dev/null +++ b/test_programs/compile_failure/nested_slice_literal/src/main.nr @@ -0,0 +1,23 @@ +struct FooParent { + parent_arr: [Field; 3], + foos: [Foo], +} + +struct Bar { + inner: [Field; 3], +} + +struct Foo { + a: Field, + b: T, + bar: Bar, +} + +fn main(x: Field, y: pub Field) { + assert(x != y); + + let foo = Foo { a: 7, b: [8, 9, 22].as_slice(), bar: Bar { inner: [106, 107, 108] } }; + let mut slice = [foo, foo]; + slice = slice.push_back(foo); + assert(slice.len() == 3); +} diff --git a/test_programs/compile_failure/nested_slice_struct/Nargo.toml b/test_programs/compile_failure/nested_slice_struct/Nargo.toml new file mode 100644 index 00000000000..a37fe6c3390 --- /dev/null +++ b/test_programs/compile_failure/nested_slice_struct/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "nested_slice_struct" +type = "bin" +authors = [""] +compiler_version = ">=0.22.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/nested_slice_struct/src/main.nr b/test_programs/compile_failure/nested_slice_struct/src/main.nr new file mode 100644 index 00000000000..9fed4cfc299 --- /dev/null +++ b/test_programs/compile_failure/nested_slice_struct/src/main.nr @@ -0,0 +1,18 @@ +struct FooParent { + parent_arr: [Field; 3], + foos: [Foo], +} + +struct Bar { + inner: [Field; 3], +} + +struct Foo { + a: Field, + b: [Field], + bar: Bar, +} + +fn main(x: Field, y: pub Field) { + assert(x != y); +} diff --git a/test_programs/compile_failure/no_impl_from_function/Nargo.toml b/test_programs/compile_failure/no_impl_from_function/Nargo.toml new file mode 100644 index 00000000000..0d243d0029d --- /dev/null +++ b/test_programs/compile_failure/no_impl_from_function/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "no_impl_from_function" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_failure/no_impl_from_function/src/main.nr b/test_programs/compile_failure/no_impl_from_function/src/main.nr new file mode 100644 index 00000000000..b0c485c2bf5 --- /dev/null +++ b/test_programs/compile_failure/no_impl_from_function/src/main.nr @@ -0,0 +1,26 @@ +fn main() { + let array: [Field; 3] = [1, 2, 3]; + assert(foo(array)); + + // Ensure this still works if we have to infer the type of the integer literals + let array = [1, 2, 3]; + assert(foo(array)); +} + +fn foo(x: T) -> bool where T: Eq { + x.eq(x) +} + +trait Eq { + fn eq(self, other: Self) -> bool; +} + +impl Eq for [T; N] where T: Eq { + fn eq(self, other: Self) -> bool { + let mut ret = true; + for i in 0 .. self.len() { + ret &= self[i].eq(other[i]); + } + ret + } +} diff --git a/test_programs/compile_failure/no_nested_impl/Nargo.toml b/test_programs/compile_failure/no_nested_impl/Nargo.toml new file mode 100644 index 00000000000..5179c0f6a5c --- /dev/null +++ b/test_programs/compile_failure/no_nested_impl/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "no_nested_impl" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/no_nested_impl/src/main.nr b/test_programs/compile_failure/no_nested_impl/src/main.nr new file mode 100644 index 00000000000..1f1056fb6d9 --- /dev/null +++ b/test_programs/compile_failure/no_nested_impl/src/main.nr @@ -0,0 +1,21 @@ +fn main() { + let a: [[[[Field; 2]; 2]; 2]; 2] = [[[[1, 2], [3, 4]], [[5, 6], [7, 8]]], [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]]; + assert(a.my_eq(a)); +} + +trait MyEq { + fn my_eq(self, other: Self) -> bool; +} + +impl MyEq for [T; 2] where T: MyEq { + fn my_eq(self, other: Self) -> bool { + self[0].my_eq(other[0]) + & self[0].my_eq(other[0]) + } +} +// Impl for u32 but not Field +impl MyEq for u32 { + fn my_eq(self, other: Self) -> bool { + self == other + } +} diff --git a/test_programs/compile_failure/option_expect_bad_input/Nargo.toml b/test_programs/compile_failure/option_expect_bad_input/Nargo.toml new file mode 100644 index 00000000000..0555681e188 --- /dev/null +++ b/test_programs/compile_failure/option_expect_bad_input/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "option_expect_bad_input" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/option_expect_bad_input/src/main.nr b/test_programs/compile_failure/option_expect_bad_input/src/main.nr new file mode 100644 index 00000000000..cc93e767975 --- /dev/null +++ b/test_programs/compile_failure/option_expect_bad_input/src/main.nr @@ -0,0 +1,6 @@ +fn main() { + let inner_value = 3; + let some = Option::some(inner_value); + + assert(some.expect("Should have the value {inner_value}") == 3); +} diff --git a/test_programs/compile_failure/orphaned_trait_impl/Nargo.toml b/test_programs/compile_failure/orphaned_trait_impl/Nargo.toml new file mode 100644 index 00000000000..89f30bb1ba5 --- /dev/null +++ b/test_programs/compile_failure/orphaned_trait_impl/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "orphaned_trait_impl" +type = "bin" +authors = [""] +[dependencies] +crate1 = { path = "crate1" } +crate2 = { path = "crate2" } diff --git a/test_programs/compile_failure/orphaned_trait_impl/crate1/Nargo.toml b/test_programs/compile_failure/orphaned_trait_impl/crate1/Nargo.toml new file mode 100644 index 00000000000..de1eddf2cf0 --- /dev/null +++ b/test_programs/compile_failure/orphaned_trait_impl/crate1/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "crate1" +type = "lib" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/orphaned_trait_impl/crate1/src/lib.nr b/test_programs/compile_failure/orphaned_trait_impl/crate1/src/lib.nr new file mode 100644 index 00000000000..4d41ff2909a --- /dev/null +++ b/test_programs/compile_failure/orphaned_trait_impl/crate1/src/lib.nr @@ -0,0 +1,2 @@ +trait MyTrait { +} diff --git a/test_programs/compile_failure/orphaned_trait_impl/crate2/Nargo.toml b/test_programs/compile_failure/orphaned_trait_impl/crate2/Nargo.toml new file mode 100644 index 00000000000..c86c5edf51a --- /dev/null +++ b/test_programs/compile_failure/orphaned_trait_impl/crate2/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "crate2" +type = "lib" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/orphaned_trait_impl/crate2/src/lib.nr b/test_programs/compile_failure/orphaned_trait_impl/crate2/src/lib.nr new file mode 100644 index 00000000000..3cadb6d78cb --- /dev/null +++ b/test_programs/compile_failure/orphaned_trait_impl/crate2/src/lib.nr @@ -0,0 +1,2 @@ +struct MyStruct { +} diff --git a/test_programs/compile_failure/orphaned_trait_impl/src/main.nr b/test_programs/compile_failure/orphaned_trait_impl/src/main.nr new file mode 100644 index 00000000000..dd04aa454b2 --- /dev/null +++ b/test_programs/compile_failure/orphaned_trait_impl/src/main.nr @@ -0,0 +1,6 @@ +impl crate1::MyTrait for crate2::MyStruct { +} + +fn main(x: Field, y: pub Field) { + assert(x != y); +} diff --git a/test_programs/compile_failure/overlapping_dep_and_mod/Nargo.toml b/test_programs/compile_failure/overlapping_dep_and_mod/Nargo.toml new file mode 100644 index 00000000000..b2c3e5f94be --- /dev/null +++ b/test_programs/compile_failure/overlapping_dep_and_mod/Nargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "bin", + "foo", +] +default-member = "bin" diff --git a/test_programs/compile_failure/overlapping_dep_and_mod/bin/Nargo.toml b/test_programs/compile_failure/overlapping_dep_and_mod/bin/Nargo.toml new file mode 100644 index 00000000000..57e704462db --- /dev/null +++ b/test_programs/compile_failure/overlapping_dep_and_mod/bin/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "overlapping_dep_and_mod" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] +foo = { path = "../foo" } diff --git a/test_programs/compile_failure/overlapping_dep_and_mod/bin/Prover.toml b/test_programs/compile_failure/overlapping_dep_and_mod/bin/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/compile_failure/overlapping_dep_and_mod/bin/src/main.nr b/test_programs/compile_failure/overlapping_dep_and_mod/bin/src/main.nr new file mode 100644 index 00000000000..675e889b7e5 --- /dev/null +++ b/test_programs/compile_failure/overlapping_dep_and_mod/bin/src/main.nr @@ -0,0 +1,12 @@ +fn main() -> pub Field { + assert(foo::bar() + foo::baz() == 3); + assert(foo::bar() == 1); + assert(foo::baz() == 2); + foo::bar() + foo::baz() +} + +mod foo { + pub(crate) fn bar() -> Field { + 1 + } +} diff --git a/test_programs/compile_failure/overlapping_dep_and_mod/foo/Nargo.toml b/test_programs/compile_failure/overlapping_dep_and_mod/foo/Nargo.toml new file mode 100644 index 00000000000..857d4e722a8 --- /dev/null +++ b/test_programs/compile_failure/overlapping_dep_and_mod/foo/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "foo" +type = "lib" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] diff --git a/test_programs/compile_failure/overlapping_dep_and_mod/foo/src/lib.nr b/test_programs/compile_failure/overlapping_dep_and_mod/foo/src/lib.nr new file mode 100644 index 00000000000..7834e2c9276 --- /dev/null +++ b/test_programs/compile_failure/overlapping_dep_and_mod/foo/src/lib.nr @@ -0,0 +1,3 @@ +pub fn baz() -> Field { + 2 +} diff --git a/test_programs/compile_failure/overlapping_generic_impls/Nargo.toml b/test_programs/compile_failure/overlapping_generic_impls/Nargo.toml new file mode 100644 index 00000000000..a279bfb053a --- /dev/null +++ b/test_programs/compile_failure/overlapping_generic_impls/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "overlapping_generic_impls" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/overlapping_generic_impls/src/main.nr b/test_programs/compile_failure/overlapping_generic_impls/src/main.nr new file mode 100644 index 00000000000..95e4d53bf93 --- /dev/null +++ b/test_programs/compile_failure/overlapping_generic_impls/src/main.nr @@ -0,0 +1,6 @@ +trait Trait { fn t(self); } + +impl Trait for T { fn t(self){} } +impl Trait for u32 { fn t(self){} } + +fn main() {} diff --git a/test_programs/compile_failure/overlapping_mod/Nargo.toml b/test_programs/compile_failure/overlapping_mod/Nargo.toml new file mode 100644 index 00000000000..c9d59b22a39 --- /dev/null +++ b/test_programs/compile_failure/overlapping_mod/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "overlapping_lib_and_mod" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/overlapping_mod/src/foo.nr b/test_programs/compile_failure/overlapping_mod/src/foo.nr new file mode 100644 index 00000000000..f17d7d7cec5 --- /dev/null +++ b/test_programs/compile_failure/overlapping_mod/src/foo.nr @@ -0,0 +1,4 @@ +pub fn bar() -> bool { + true +} + diff --git a/test_programs/compile_failure/overlapping_mod/src/foo/mod.nr b/test_programs/compile_failure/overlapping_mod/src/foo/mod.nr new file mode 100644 index 00000000000..261729b812b --- /dev/null +++ b/test_programs/compile_failure/overlapping_mod/src/foo/mod.nr @@ -0,0 +1,3 @@ +pub fn bar() -> bool { + true +} diff --git a/test_programs/compile_failure/overlapping_mod/src/main.nr b/test_programs/compile_failure/overlapping_mod/src/main.nr new file mode 100644 index 00000000000..12a3d91f941 --- /dev/null +++ b/test_programs/compile_failure/overlapping_mod/src/main.nr @@ -0,0 +1,7 @@ +mod foo; + +use foo::bar; + +fn main() { + assert(bar()); +} diff --git a/test_programs/compile_failure/package_name_empty/Nargo.toml b/test_programs/compile_failure/package_name_empty/Nargo.toml new file mode 100644 index 00000000000..88382674780 --- /dev/null +++ b/test_programs/compile_failure/package_name_empty/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_failure/package_name_empty/src/main.nr b/test_programs/compile_failure/package_name_empty/src/main.nr new file mode 100644 index 00000000000..faf1ba0045a --- /dev/null +++ b/test_programs/compile_failure/package_name_empty/src/main.nr @@ -0,0 +1 @@ +fn main(x: Field) { } diff --git a/test_programs/compile_failure/package_name_hyphen/Nargo.toml b/test_programs/compile_failure/package_name_hyphen/Nargo.toml new file mode 100644 index 00000000000..4882b83b8bf --- /dev/null +++ b/test_programs/compile_failure/package_name_hyphen/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "hyphenated-name" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_failure/package_name_hyphen/src/main.nr b/test_programs/compile_failure/package_name_hyphen/src/main.nr new file mode 100644 index 00000000000..faf1ba0045a --- /dev/null +++ b/test_programs/compile_failure/package_name_hyphen/src/main.nr @@ -0,0 +1 @@ +fn main(x: Field) { } diff --git a/test_programs/compile_failure/primary_attribute_struct/Nargo.toml b/test_programs/compile_failure/primary_attribute_struct/Nargo.toml new file mode 100644 index 00000000000..7c5e7f70774 --- /dev/null +++ b/test_programs/compile_failure/primary_attribute_struct/Nargo.toml @@ -0,0 +1,7 @@ + +[package] +name = "primary_attribute_struct" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/primary_attribute_struct/src/main.nr b/test_programs/compile_failure/primary_attribute_struct/src/main.nr new file mode 100644 index 00000000000..8922ef60091 --- /dev/null +++ b/test_programs/compile_failure/primary_attribute_struct/src/main.nr @@ -0,0 +1,8 @@ +// An primary attribute should not be able to be added to a struct defintion +#[oracle(some_oracle)] +struct SomeStruct{ + x: Field, + y: Field +} + +fn main() {} diff --git a/test_programs/compile_failure/quote_at_runtime/Nargo.toml b/test_programs/compile_failure/quote_at_runtime/Nargo.toml new file mode 100644 index 00000000000..3ce62412b32 --- /dev/null +++ b/test_programs/compile_failure/quote_at_runtime/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "quote_at_runtime" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_failure/quote_at_runtime/src/main.nr b/test_programs/compile_failure/quote_at_runtime/src/main.nr new file mode 100644 index 00000000000..5da409682f6 --- /dev/null +++ b/test_programs/compile_failure/quote_at_runtime/src/main.nr @@ -0,0 +1,7 @@ +fn main() { + foo(quote { test }) +} + +fn foo(q: Quoted) { + println(q); +} diff --git a/test_programs/compile_failure/raw_string_huge/Nargo.toml b/test_programs/compile_failure/raw_string_huge/Nargo.toml new file mode 100644 index 00000000000..ecef0e2a07c --- /dev/null +++ b/test_programs/compile_failure/raw_string_huge/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "raw_string_huge" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/raw_string_huge/src/main.nr b/test_programs/compile_failure/raw_string_huge/src/main.nr new file mode 100644 index 00000000000..7bca9942e7a --- /dev/null +++ b/test_programs/compile_failure/raw_string_huge/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + // Fails because of too many hashes for raw string (256+ hashes) + let _a = r##############################################################################################################################################################################################################################################################################"hello"##############################################################################################################################################################################################################################################################################; +} diff --git a/test_programs/compile_failure/regression_5008/Nargo.toml b/test_programs/compile_failure/regression_5008/Nargo.toml new file mode 100644 index 00000000000..920c00660cf --- /dev/null +++ b/test_programs/compile_failure/regression_5008/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5008" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] diff --git a/test_programs/compile_failure/regression_5008/src/main.nr b/test_programs/compile_failure/regression_5008/src/main.nr new file mode 100644 index 00000000000..5155900734c --- /dev/null +++ b/test_programs/compile_failure/regression_5008/src/main.nr @@ -0,0 +1,18 @@ +struct Bar { + value: Field, +} + +struct Foo { + bar: &mut Bar, +} + +impl Foo { + unconstrained fn crash_fn(self) {} +} + +fn main() { + let foo = Foo { bar: &mut Bar { value: 0 } }; + + /// Safety: testing context + unsafe { foo.crash_fn() }; +} 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/restricted_bit_sizes/Nargo.toml b/test_programs/compile_failure/restricted_bit_sizes/Nargo.toml new file mode 100644 index 00000000000..36f8253e8e7 --- /dev/null +++ b/test_programs/compile_failure/restricted_bit_sizes/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "restricted_bit_sizes" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_failure/restricted_bit_sizes/src/main.nr b/test_programs/compile_failure/restricted_bit_sizes/src/main.nr new file mode 100644 index 00000000000..a3fea13cc3a --- /dev/null +++ b/test_programs/compile_failure/restricted_bit_sizes/src/main.nr @@ -0,0 +1,5 @@ +use std::assert_constant; + +fn main() -> pub u63 { + 5 +} 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/signed_integer_literal_overflow/Nargo.toml b/test_programs/compile_failure/signed_integer_literal_overflow/Nargo.toml new file mode 100644 index 00000000000..d6aaf3a79d4 --- /dev/null +++ b/test_programs/compile_failure/signed_integer_literal_overflow/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "signed_integer_literal_overflow" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/signed_integer_literal_overflow/src/main.nr b/test_programs/compile_failure/signed_integer_literal_overflow/src/main.nr new file mode 100644 index 00000000000..e6c87da9c29 --- /dev/null +++ b/test_programs/compile_failure/signed_integer_literal_overflow/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + foo(128) +} + +fn foo(_x: i8) {} diff --git a/test_programs/compile_failure/signed_integer_literal_underflow/Nargo.toml b/test_programs/compile_failure/signed_integer_literal_underflow/Nargo.toml new file mode 100644 index 00000000000..75a01881d2e --- /dev/null +++ b/test_programs/compile_failure/signed_integer_literal_underflow/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "signed_integer_literal_underflow" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/signed_integer_literal_underflow/src/main.nr b/test_programs/compile_failure/signed_integer_literal_underflow/src/main.nr new file mode 100644 index 00000000000..eb50a3890e6 --- /dev/null +++ b/test_programs/compile_failure/signed_integer_literal_underflow/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + foo(-129) +} + +fn foo(_x: i8) {} diff --git a/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml b/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml new file mode 100644 index 00000000000..1c6c13ce225 --- /dev/null +++ b/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert_dynamic_array_len" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr b/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr new file mode 100644 index 00000000000..9e4665f8ad8 --- /dev/null +++ b/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + std::static_assert([1, 2, dynamic_one].len() == 4, ""); +} diff --git a/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml b/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml new file mode 100644 index 00000000000..45e39ae24a8 --- /dev/null +++ b/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert_dynamic_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr b/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr new file mode 100644 index 00000000000..6621b8a1fb3 --- /dev/null +++ b/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr @@ -0,0 +1,15 @@ +fn main( + dynamic_one: Field, // == 1 + dynamic_two: Field, // == 2 +) { + // length unknown at compile time + let mut dynamic_built_slice_pair = &[]; + if dynamic_one == 1 { + dynamic_built_slice_pair = dynamic_built_slice_pair.push_back(dynamic_one); + } + if dynamic_two == 2 { + dynamic_built_slice_pair = dynamic_built_slice_pair.push_back(dynamic_two); + } + + std::static_assert(dynamic_built_slice_pair.len() == 3, ""); +} diff --git a/test_programs/compile_failure/static_assert_plus/Nargo.toml b/test_programs/compile_failure/static_assert_plus/Nargo.toml new file mode 100644 index 00000000000..fdb90c0dc1c --- /dev/null +++ b/test_programs/compile_failure/static_assert_plus/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert_plus" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/static_assert_plus/src/main.nr b/test_programs/compile_failure/static_assert_plus/src/main.nr new file mode 100644 index 00000000000..2241743ddb0 --- /dev/null +++ b/test_programs/compile_failure/static_assert_plus/src/main.nr @@ -0,0 +1,7 @@ +fn main() { + let x = 2; + let y = 3; + let xy = x + y; + + std::static_assert(xy == 6, "2 + 3 != 6"); +} diff --git a/test_programs/compile_failure/trait_incorrect_generic_count/Nargo.toml b/test_programs/compile_failure/trait_incorrect_generic_count/Nargo.toml new file mode 100644 index 00000000000..379e964d70a --- /dev/null +++ b/test_programs/compile_failure/trait_incorrect_generic_count/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "trait_incorrect_generic_count" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/trait_incorrect_generic_count/src/main.nr b/test_programs/compile_failure/trait_incorrect_generic_count/src/main.nr new file mode 100644 index 00000000000..d65d55894ea --- /dev/null +++ b/test_programs/compile_failure/trait_incorrect_generic_count/src/main.nr @@ -0,0 +1,12 @@ +fn main() { + let x: u32 = 0; + x.trait_fn(); +} + +trait Trait { + fn trait_fn(x: T) -> T {} +} + +impl Trait for u32 { + fn trait_fn(x: A) -> A { x } +} diff --git a/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..5dc05a3a5c3 --- /dev/null +++ b/test_programs/compile_failure/turbofish_generic_count/src/main.nr @@ -0,0 +1,21 @@ +struct Bar { + one: Field, + two: Field, + other: T, +} + +impl Bar { + fn zeroed(_self: Self) -> A { + std::mem::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/type_annotation_needed_on_struct_constructor/Nargo.toml b/test_programs/compile_failure/type_annotation_needed_on_struct_constructor/Nargo.toml new file mode 100644 index 00000000000..ac7933fa250 --- /dev/null +++ b/test_programs/compile_failure/type_annotation_needed_on_struct_constructor/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "type_annotation_needed_on_struct_constructor" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/type_annotation_needed_on_struct_constructor/src/main.nr b/test_programs/compile_failure/type_annotation_needed_on_struct_constructor/src/main.nr new file mode 100644 index 00000000000..5207210dfbf --- /dev/null +++ b/test_programs/compile_failure/type_annotation_needed_on_struct_constructor/src/main.nr @@ -0,0 +1,6 @@ +struct Foo { +} + +fn main() { + let foo = Foo {}; +} diff --git a/test_programs/compile_failure/type_annotation_needed_on_struct_new/Nargo.toml b/test_programs/compile_failure/type_annotation_needed_on_struct_new/Nargo.toml new file mode 100644 index 00000000000..cb53d2924f4 --- /dev/null +++ b/test_programs/compile_failure/type_annotation_needed_on_struct_new/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "type_annotation_needed_on_struct_new" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/type_annotation_needed_on_struct_new/src/main.nr b/test_programs/compile_failure/type_annotation_needed_on_struct_new/src/main.nr new file mode 100644 index 00000000000..f740dfa6d37 --- /dev/null +++ b/test_programs/compile_failure/type_annotation_needed_on_struct_new/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { +} + +impl Foo { + fn new() -> Foo { + Foo {} + } +} + +fn main() { + let foo = Foo::new(); +} diff --git a/test_programs/compile_failure/type_definition_annotation/Nargo.toml b/test_programs/compile_failure/type_definition_annotation/Nargo.toml new file mode 100644 index 00000000000..dc90816e16b --- /dev/null +++ b/test_programs/compile_failure/type_definition_annotation/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "type_definition_annotation" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/type_definition_annotation/src/main.nr b/test_programs/compile_failure/type_definition_annotation/src/main.nr new file mode 100644 index 00000000000..d4fef84442d --- /dev/null +++ b/test_programs/compile_failure/type_definition_annotation/src/main.nr @@ -0,0 +1,8 @@ +#[fail_assert] +struct Foo { x: Field } + +comptime fn fail_assert(_typ: StructDefinition) { + assert(false); +} + +fn main() {} 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/unary_not_on_field_type_variable/Nargo.toml b/test_programs/compile_failure/unary_not_on_field_type_variable/Nargo.toml new file mode 100644 index 00000000000..ae5c9ecb9c9 --- /dev/null +++ b/test_programs/compile_failure/unary_not_on_field_type_variable/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unary_not_on_field_type_variable" +type = "bin" +authors = [""] +compiler_version = "" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/unary_not_on_field_type_variable/src/main.nr b/test_programs/compile_failure/unary_not_on_field_type_variable/src/main.nr new file mode 100644 index 00000000000..1023f753c32 --- /dev/null +++ b/test_programs/compile_failure/unary_not_on_field_type_variable/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + let num: Field = 0; + assert_eq(!0, num); +} 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..23dc1d66673 --- /dev/null +++ b/test_programs/compile_failure/unconstrained_ref/src/main.nr @@ -0,0 +1,9 @@ +unconstrained fn uncon_ref() -> &mut Field { + let lr = &mut 7; + lr +} + +fn main() { + /// Safety: testing context + let e = unsafe { uncon_ref() }; +} diff --git a/test_programs/compile_failure/unsigned_integer_literal_overflow/Nargo.toml b/test_programs/compile_failure/unsigned_integer_literal_overflow/Nargo.toml new file mode 100644 index 00000000000..1e787d9082e --- /dev/null +++ b/test_programs/compile_failure/unsigned_integer_literal_overflow/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "unsigned_integer_literal_overflow" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/unsigned_integer_literal_overflow/src/main.nr b/test_programs/compile_failure/unsigned_integer_literal_overflow/src/main.nr new file mode 100644 index 00000000000..e4d21b5c3b9 --- /dev/null +++ b/test_programs/compile_failure/unsigned_integer_literal_overflow/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + foo(1234) +} + +fn foo(_x: u8) {} diff --git a/test_programs/compile_failure/unsigned_integer_literal_underflow/Nargo.toml b/test_programs/compile_failure/unsigned_integer_literal_underflow/Nargo.toml new file mode 100644 index 00000000000..ae8152caecc --- /dev/null +++ b/test_programs/compile_failure/unsigned_integer_literal_underflow/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "unsigned_integer_literal_underflow" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/unsigned_integer_literal_underflow/src/main.nr b/test_programs/compile_failure/unsigned_integer_literal_underflow/src/main.nr new file mode 100644 index 00000000000..217003a013f --- /dev/null +++ b/test_programs/compile_failure/unsigned_integer_literal_underflow/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + foo(-1) +} + +fn foo(_x: u8) {} diff --git a/test_programs/compile_failure/unspecified_generic/Nargo.toml b/test_programs/compile_failure/unspecified_generic/Nargo.toml new file mode 100644 index 00000000000..15b97018f2d --- /dev/null +++ b/test_programs/compile_failure/unspecified_generic/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unspecified_generic" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_failure/unspecified_generic/src/main.nr b/test_programs/compile_failure/unspecified_generic/src/main.nr new file mode 100644 index 00000000000..f26d794d567 --- /dev/null +++ b/test_programs/compile_failure/unspecified_generic/src/main.nr @@ -0,0 +1,5 @@ +fn foo() {} + +fn main() { + foo(); +} diff --git a/test_programs/compile_failure/workspace_missing_toml/Nargo.toml b/test_programs/compile_failure/workspace_missing_toml/Nargo.toml new file mode 100644 index 00000000000..36db098686f --- /dev/null +++ b/test_programs/compile_failure/workspace_missing_toml/Nargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["crates/a", "crates/b"] diff --git a/test_programs/compile_failure/workspace_missing_toml/crates/a/src/main.nr b/test_programs/compile_failure/workspace_missing_toml/crates/a/src/main.nr new file mode 100644 index 00000000000..cf72627da2e --- /dev/null +++ b/test_programs/compile_failure/workspace_missing_toml/crates/a/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x == y); +} diff --git a/test_programs/compile_failure/workspace_missing_toml/crates/b/Nargo.toml b/test_programs/compile_failure/workspace_missing_toml/crates/b/Nargo.toml new file mode 100644 index 00000000000..f316511340f --- /dev/null +++ b/test_programs/compile_failure/workspace_missing_toml/crates/b/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "b" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_failure/workspace_missing_toml/crates/b/src/main.nr b/test_programs/compile_failure/workspace_missing_toml/crates/b/src/main.nr new file mode 100644 index 00000000000..4e1fd3c9035 --- /dev/null +++ b/test_programs/compile_failure/workspace_missing_toml/crates/b/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x != y); +} diff --git a/test_programs/compile_success_contract/abi_attribute/Nargo.toml b/test_programs/compile_success_contract/abi_attribute/Nargo.toml new file mode 100644 index 00000000000..56fa88ccb68 --- /dev/null +++ b/test_programs/compile_success_contract/abi_attribute/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "abi_attribute" +type = "contract" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_contract/abi_attribute/src/main.nr b/test_programs/compile_success_contract/abi_attribute/src/main.nr new file mode 100644 index 00000000000..c4d4a24e3c2 --- /dev/null +++ b/test_programs/compile_success_contract/abi_attribute/src/main.nr @@ -0,0 +1,9 @@ +contract Foo { + #[abi(foo)] + pub global foo: Field = 42; + + #[abi(bar)] + pub struct Bar { + inner: Field + } +} diff --git a/test_programs/compile_success_contract/contract_with_impl/Nargo.toml b/test_programs/compile_success_contract/contract_with_impl/Nargo.toml new file mode 100644 index 00000000000..ed5e9ec0910 --- /dev/null +++ b/test_programs/compile_success_contract/contract_with_impl/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "simple_contract" +type = "contract" +authors = [""] + +[dependencies] + 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 new file mode 100644 index 00000000000..9d45b88fbc9 --- /dev/null +++ b/test_programs/compile_success_contract/contract_with_impl/src/main.nr @@ -0,0 +1,9 @@ +contract Foo { + pub struct T { x: [Field] } + + impl T { + fn t(self) { + let _ = 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/non_entry_point_method/Nargo.toml b/test_programs/compile_success_contract/non_entry_point_method/Nargo.toml new file mode 100644 index 00000000000..fb1969acc43 --- /dev/null +++ b/test_programs/compile_success_contract/non_entry_point_method/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "no_entry_points" +type = "contract" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_contract/non_entry_point_method/src/main.nr b/test_programs/compile_success_contract/non_entry_point_method/src/main.nr new file mode 100644 index 00000000000..f49c2f14f9d --- /dev/null +++ b/test_programs/compile_success_contract/non_entry_point_method/src/main.nr @@ -0,0 +1,6 @@ +contract Foo { + pub struct PlaceholderStruct{x : u32 } + + #[contract_library_method] + pub fn has_mut(_context: &mut PlaceholderStruct) {} +} diff --git a/test_programs/compile_success_contract/simple_contract/Nargo.toml b/test_programs/compile_success_contract/simple_contract/Nargo.toml new file mode 100644 index 00000000000..ed5e9ec0910 --- /dev/null +++ b/test_programs/compile_success_contract/simple_contract/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "simple_contract" +type = "contract" +authors = [""] + +[dependencies] + diff --git a/test_programs/compile_success_contract/simple_contract/src/main.nr b/test_programs/compile_success_contract/simple_contract/src/main.nr new file mode 100644 index 00000000000..7742ed6139b --- /dev/null +++ b/test_programs/compile_success_contract/simple_contract/src/main.nr @@ -0,0 +1,16 @@ +contract Foo { + fn double(x: Field) -> pub Field { + x * 2 + } + fn triple(x: Field) -> pub Field { + x * 3 + } + fn quadruple(x: Field) -> pub Field { + x * 4 + } + // Regression for issue #3344 + #[contract_library_method] + pub fn foo(x: u8) -> u8 { + x + } +} diff --git a/test_programs/compile_success_empty/acir_inside_brillig_recursion/Nargo.toml b/test_programs/compile_success_empty/acir_inside_brillig_recursion/Nargo.toml new file mode 100644 index 00000000000..462532bb484 --- /dev/null +++ b/test_programs/compile_success_empty/acir_inside_brillig_recursion/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "acir_inside_brillig_recursion" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/acir_inside_brillig_recursion/src/main.nr b/test_programs/compile_success_empty/acir_inside_brillig_recursion/src/main.nr new file mode 100644 index 00000000000..12c663b2705 --- /dev/null +++ b/test_programs/compile_success_empty/acir_inside_brillig_recursion/src/main.nr @@ -0,0 +1,18 @@ +fn main() { + /// Safety: testing context + unsafe { + 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/compile_success_empty/arithmetic_generics/Nargo.toml b/test_programs/compile_success_empty/arithmetic_generics/Nargo.toml new file mode 100644 index 00000000000..2352ae0c562 --- /dev/null +++ b/test_programs/compile_success_empty/arithmetic_generics/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "arithmetic_generics" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/arithmetic_generics/src/main.nr b/test_programs/compile_success_empty/arithmetic_generics/src/main.nr new file mode 100644 index 00000000000..ae50748c8e7 --- /dev/null +++ b/test_programs/compile_success_empty/arithmetic_generics/src/main.nr @@ -0,0 +1,144 @@ +fn main() { + let (first, rest) = split_first([1, 2, 3, 4]); + assert_eq(first, 1); + assert_eq(rest, [2, 3, 4]); + + // Type inference works without the type constraints from assert_eq as well + let _ = split_first([1, 2, 3]); + + let _ = push_multiple([1, 2, 3]); + + test_constant_folding::<10>(); + test_non_constant_folding::<10, 20>(); +} + +fn split_first(array: [T; N]) -> (T, [T; N - 1]) { + std::static_assert(N != 0, "split_first called on empty array"); + let mut new_array: [T; N - 1] = std::mem::zeroed(); + + for i in 0..N - 1 { + new_array[i] = array[i + 1]; + } + + (array[0], new_array) +} + +fn push(array: [Field; N], element: Field) -> [Field; N + 1] { + let mut result: [_; N + 1] = std::mem::zeroed(); + result[array.len()] = element; + + for i in 0..array.len() { + result[i] = array[i]; + } + + result +} + +fn push_multiple(array: [Field; N]) -> [Field; N + 2] { + // : [Field; N + 1] + let array2 = push(array, 4); + + // : [Field; (N + 1) + 1] + let array3 = push(array2, 5); + + // [Field; (N + 1) + 1] = [Field; N + 2] + array3 +} + +// This signature fails because we can't match `_ + 1` to `3` at the call site +// fn push_multiple(array: [Field; 1 + N]) -> [Field; N + 3] { + +// ********************************************* +// The rest of this file is setup for demo_proof +// ********************************************* + +pub struct W {} + +pub struct Equiv { + // TODO(https://github.com/noir-lang/noir/issues/5644): + // Bug with struct_obj.field_thats_a_fn(x) + + to_: fn[TU](T) -> U, + fro_: fn[UT](U) -> T, + // .. other coherence conditions +} + +impl Equiv { + fn to(self, x: T) -> U { + (self.to_)(x) + } + + fn fro(self, x: U) -> T { + (self.fro_)(x) + } +} + +fn equiv_trans( + x: Equiv, + y: Equiv, + ) -> Equiv, Equiv), V, (Equiv, Equiv)> { + Equiv { to_: |z| y.to(x.to(z)), fro_: |z| x.fro(y.fro(z)) } +} + +fn mul_one_r() -> Equiv, (), W, ()> { + Equiv { to_: |_x| W {}, fro_: |_x| W {} } +} + +fn add_equiv_r( + _: Equiv, EN, W, EM>, +) -> Equiv, (), W, ()> { + Equiv { to_: |_x| W {}, fro_: |_x| W {} } +} + +fn mul_comm() -> Equiv, (), W, ()> { + Equiv { to_: |_x| W {}, fro_: |_x| W {} } +} + +fn mul_add() -> Equiv, (), W, ()> { + Equiv { to_: |_x| W {}, fro_: |_x| W {} } +} + +// (N + 1) * N == N * N + N +pub fn demo_proof() -> Equiv, (Equiv, (), W, ()>, Equiv, (Equiv, (), W, ()>, Equiv, (), W<(N * (N + 1))>, ()>), W, (Equiv, (), W<(N * (N + 1))>, ()>, Equiv, (), W, ()>)>), W, (Equiv, (Equiv, (), W, ()>, Equiv, (), W<(N * (N + 1))>, ()>), W, (Equiv, (), W<(N * (N + 1))>, ()>, Equiv, (), W, ()>)>, Equiv, (), W, ()>)> { + let p1: Equiv, (), W, ()> = mul_comm(); + let p2: Equiv, (), W, ()> = mul_add::(); + let p3_sub: Equiv, (), W, ()> = mul_one_r(); + let _p3: Equiv, (), W, ()> = add_equiv_r::(p3_sub); + let _p1_to_2 = equiv_trans(p1, p2); + + // equiv_trans(p1_to_2, p3) + std::mem::zeroed() +} + +fn test_constant_folding() { + // N + C1 - C2 = N + (C1 - C2) + let _: W = W:: {}; + + // N - C1 + C2 = N - (C1 - C2) + let _: W = W:: {}; + + // N * C1 / C2 = N * (C1 / C2) + let _: W = W:: {}; + // This case is invalid due to integer division + // If N does not divide evenly with 10 then we cannot simplify it. + // e.g. 15 / 10 * 2 = 2 versus 15 / 5 = 3 + // + // N / C1 * C2 = N / (C1 / C2) + // let _: W = W:: {}; +} + +fn test_non_constant_folding() { + // N + M - M = N + let _: W = W:: {}; + + // N - M + M = N + let _: W = W:: {}; + + // N * M / M = N + let _: W = W:: {}; + // This case is not true due to integer division rounding! + // Consider 5 / 2 * 2 which should equal 4, not 5 + // + // N / M * M = N + // let _: W = W:: {}; +} diff --git a/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/Nargo.toml b/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/Nargo.toml new file mode 100644 index 00000000000..8d057a77814 --- /dev/null +++ b/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "arithmetic_generics_move_constant_terms" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/src/main.nr b/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/src/main.nr new file mode 100644 index 00000000000..4a9b1489d35 --- /dev/null +++ b/test_programs/compile_success_empty/arithmetic_generics_move_constant_terms/src/main.nr @@ -0,0 +1,29 @@ +trait FromCallData { + fn from_calldata(calldata: [Field; N]) -> (Self, [Field; M]); +} + +struct Point { + x: Field, + y: Field, +} + +impl FromCallData for Field { + fn from_calldata(calldata: [Field; N]) -> (Self, [Field; N - 1]) { + let slice = calldata.as_slice(); + let (value, slice) = slice.pop_front(); + (value, slice.as_array()) + } +} + +impl FromCallData for Point { + fn from_calldata(calldata: [Field; N]) -> (Self, [Field; N - 2]) { + let (x, calldata) = FromCallData::from_calldata(calldata); + let (y, calldata) = FromCallData::from_calldata(calldata); + (Self { x, y }, calldata) + } +} + +fn main() { + let calldata = [1, 2]; + let _: (Point, _) = FromCallData::from_calldata(calldata); +} diff --git a/test_programs/compile_success_empty/assert_constant/Nargo.toml b/test_programs/compile_success_empty/assert_constant/Nargo.toml new file mode 100644 index 00000000000..f18d4828fdf --- /dev/null +++ b/test_programs/compile_success_empty/assert_constant/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/assert_constant/src/main.nr b/test_programs/compile_success_empty/assert_constant/src/main.nr new file mode 100644 index 00000000000..42d66f88137 --- /dev/null +++ b/test_programs/compile_success_empty/assert_constant/src/main.nr @@ -0,0 +1,59 @@ +use std::static_assert; + +global GLOBAL_ONE: Field = 1; +global GLOBAL_TWO: Field = 2; +global GLOBAL_THREE: Field = GLOBAL_ONE + GLOBAL_TWO; + +// contents known at compile time +// length known at compile time +global GLOBAL_ARRAY_PAIR: [Field; 2] = [GLOBAL_ONE, GLOBAL_TWO]; +global GLOBAL_SLICE_PAIR: [Field] = &[GLOBAL_ONE, GLOBAL_TWO]; + +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 + dynamic_two: Field, // == 2 +) { + // contents unknown at compile time + // length known at compile time + let dynamic_array_pair = [dynamic_one, dynamic_two]; + let dynamic_slice_pair = &[dynamic_one, dynamic_two]; + + assert_constant(true); + assert_constant(false); + + assert_constant(2 == 2); + assert_constant(1 + 1 == 2); + + // assert_constant doesn't check for true + assert_constant(1 + 1 == 3); + + let local_one = 1; + let local_two = 2; + let local_three = local_one + local_two; + let local_array_pair = [local_one, local_two]; + let local_slice_pair = &[local_one, local_two]; + + assert_constant(local_one); + assert_constant(local_three); + assert_constant(local_array_pair); + assert_constant(local_slice_pair); + + assert_constant(GLOBAL_ONE); + assert_constant(GLOBAL_THREE); + assert_constant(GLOBAL_ARRAY_PAIR); + assert_constant(GLOBAL_SLICE_PAIR); + + assert_constant([1, 2, dynamic_one].len() == 4); + + static_assert(dynamic_array_pair.len() == 2, ""); + static_assert(dynamic_slice_pair.len() == 2, ""); + + let foo = Foo { field: 0, array: [1, 2, 3], slice: &[] }; + assert_constant(foo); +} diff --git a/test_programs/compile_success_empty/associated_types/Nargo.toml b/test_programs/compile_success_empty/associated_types/Nargo.toml new file mode 100644 index 00000000000..99b8e1b2d47 --- /dev/null +++ b/test_programs/compile_success_empty/associated_types/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "associated_types" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/associated_types/src/main.nr b/test_programs/compile_success_empty/associated_types/src/main.nr new file mode 100644 index 00000000000..dbc6a393ec9 --- /dev/null +++ b/test_programs/compile_success_empty/associated_types/src/main.nr @@ -0,0 +1,28 @@ +trait Collection { + type Elem; + + fn cget(self, index: u32) -> Option; + + fn ctake(self, index: u32) -> Self::Elem { + self.cget(index).unwrap() + } +} + +impl Collection for [T; N] { + type Elem = T; + + fn cget(self, index: u32) -> Option { + if index < self.len() { + Option::some(self[index]) + } else { + Option::none() + } + } +} + +fn main() { + // Use zeroed here so that we don't help by adding another type constraint. + // We should know Elem = Field from the associated type alone. + let array = [1, 2, 3, 0, 5]; + assert_eq(array.ctake(3), std::mem::zeroed()); +} diff --git a/test_programs/compile_success_empty/associated_types_implicit/Nargo.toml b/test_programs/compile_success_empty/associated_types_implicit/Nargo.toml new file mode 100644 index 00000000000..6b54cbfca6a --- /dev/null +++ b/test_programs/compile_success_empty/associated_types_implicit/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "associated_types_implicit" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/associated_types_implicit/Prover.toml b/test_programs/compile_success_empty/associated_types_implicit/Prover.toml new file mode 100644 index 00000000000..cab679b4b66 --- /dev/null +++ b/test_programs/compile_success_empty/associated_types_implicit/Prover.toml @@ -0,0 +1 @@ +a = [[0, 1], [2, 3]] diff --git a/test_programs/compile_success_empty/associated_types_implicit/src/main.nr b/test_programs/compile_success_empty/associated_types_implicit/src/main.nr new file mode 100644 index 00000000000..d04cef51868 --- /dev/null +++ b/test_programs/compile_success_empty/associated_types_implicit/src/main.nr @@ -0,0 +1,60 @@ +trait Foo { + type Bar; + + fn foo(self) -> Self::Bar; +} + +impl Foo for u64 { + type Bar = u8; + + fn foo(self) -> Self::Bar { + self as u8 + } +} + +fn main() { + // This currently requires a type annotation to find the impl + let three: u64 = 3; + call_foo(three); + + let x: Option> = Option::some(Option::some(0)); + let x_foo = x.foo(); + assert_eq(x_foo, x_foo); // ensure we don't need an additional type annotation for Bar here + + // The `as u8` is still necessary even though we know the object type, + // otherwise we try to search for `u64: Foo`. + // It seems the `Bar = u8` constraint is still there & checked for, but + // the defaulting of the polymorphic integer occurs first. + assert_eq(x.foo(), 0 as u8); +} + +// Ensure we can use `::Bar: Eq` in a function's where clause +fn call_foo(x: T) +where + T: Foo, + ::Bar: Eq, +{ + let y = x.foo(); + assert_eq(y, y); +} + +// Ensure we can use `::Bar: Eq` in a trait impl's where clause +impl Foo for Option +where + T: Foo, + ::Bar: Eq, +{ + type Bar = ::Bar; + + fn foo(self) -> Self::Bar { + self.unwrap().foo() + } +} + +// Ensure we can use `::Bar: Eq` in a trait's where clause +// TODO: Not working, see issue #7024 +// trait Baz where +// T: Foo, +// ::Bar: Eq {} +// +// impl Baz for u32 {} diff --git a/test_programs/compile_success_empty/attribute_args/Nargo.toml b/test_programs/compile_success_empty/attribute_args/Nargo.toml new file mode 100644 index 00000000000..8efe5d203d1 --- /dev/null +++ b/test_programs/compile_success_empty/attribute_args/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "attribute_args" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/attribute_args/src/main.nr b/test_programs/compile_success_empty/attribute_args/src/main.nr new file mode 100644 index 00000000000..29690ba36c7 --- /dev/null +++ b/test_programs/compile_success_empty/attribute_args/src/main.nr @@ -0,0 +1,21 @@ +#[attr_with_args(1, 2)] +#[attr_with_varargs(1, 2)] +#[attr_with_varargs(1, 2, 3, 4)] +pub struct Foo {} + +comptime fn attr_with_args(s: StructDefinition, a: Field, b: Field) { + // Ensure all variables are in scope. + // We can't print them since that breaks the test runner. + let _ = s; + let _ = a; + let _ = b; +} + +#[varargs] +comptime fn attr_with_varargs(s: StructDefinition, t: [Field]) { + let _ = s; + for _ in t {} + assert(t.len() < 5); +} + +fn main() {} diff --git a/test_programs/compile_success_empty/attribute_order/Nargo.toml b/test_programs/compile_success_empty/attribute_order/Nargo.toml new file mode 100644 index 00000000000..4471bed86dc --- /dev/null +++ b/test_programs/compile_success_empty/attribute_order/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "attribute_order" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/attribute_order/src/a.nr b/test_programs/compile_success_empty/attribute_order/src/a.nr new file mode 100644 index 00000000000..663643f1288 --- /dev/null +++ b/test_programs/compile_success_empty/attribute_order/src/a.nr @@ -0,0 +1,13 @@ +// This is run fifth, after each child module finishes even though +// the function comes before the module declarations in the source. +#[crate::assert_run_order_function(4)] +pub fn foo() {} + +mod a_child1; +mod a_child2; + +#[crate::assert_run_order_struct(5)] +pub struct Bar {} + +#[crate::assert_run_order_trait(6)] +pub trait Foo {} diff --git a/test_programs/compile_success_empty/attribute_order/src/a/a_child1.nr b/test_programs/compile_success_empty/attribute_order/src/a/a_child1.nr new file mode 100644 index 00000000000..834bbd43fb5 --- /dev/null +++ b/test_programs/compile_success_empty/attribute_order/src/a/a_child1.nr @@ -0,0 +1,5 @@ +#[crate::assert_run_order_function(0)] +pub fn foo() {} + +#[crate::assert_run_order_struct(1)] +pub struct Foo {} diff --git a/test_programs/compile_success_empty/attribute_order/src/a/a_child2.nr b/test_programs/compile_success_empty/attribute_order/src/a/a_child2.nr new file mode 100644 index 00000000000..3548f4450a5 --- /dev/null +++ b/test_programs/compile_success_empty/attribute_order/src/a/a_child2.nr @@ -0,0 +1,5 @@ +#[crate::assert_run_order_trait(2)] +pub trait Foo {} + +#[crate::assert_run_order_function(3)] +pub fn foo() {} diff --git a/test_programs/compile_success_empty/attribute_order/src/b/b_child1.nr b/test_programs/compile_success_empty/attribute_order/src/b/b_child1.nr new file mode 100644 index 00000000000..a8e7e898ec1 --- /dev/null +++ b/test_programs/compile_success_empty/attribute_order/src/b/b_child1.nr @@ -0,0 +1,4 @@ +#[crate::assert_run_order_function(8)] +pub fn foo() {} + +#![crate::assert_run_order_module(9)] diff --git a/test_programs/compile_success_empty/attribute_order/src/b/b_child2.nr b/test_programs/compile_success_empty/attribute_order/src/b/b_child2.nr new file mode 100644 index 00000000000..8e6d967707a --- /dev/null +++ b/test_programs/compile_success_empty/attribute_order/src/b/b_child2.nr @@ -0,0 +1,2 @@ +#[crate::assert_run_order_function(7)] +pub fn foo() {} diff --git a/test_programs/compile_success_empty/attribute_order/src/b/mod.nr b/test_programs/compile_success_empty/attribute_order/src/b/mod.nr new file mode 100644 index 00000000000..77df04e15a9 --- /dev/null +++ b/test_programs/compile_success_empty/attribute_order/src/b/mod.nr @@ -0,0 +1,25 @@ +// Declare these in reverse order to ensure the declaration +// order here is respected +mod b_child2; + +#[crate::assert_run_order_module(12)] +mod b_child1; + +#[crate::assert_run_order_function(13)] +pub fn foo() {} + +#![crate::assert_run_order_module(14)] + +// Test inline submodules as well +#[crate::assert_run_order_module(15)] +mod b_child3 { + #![crate::assert_run_order_module(10)] + + #[crate::assert_run_order_function(11)] + pub fn foo() {} +} + +#[crate::assert_run_order_function(16)] +pub fn bar() {} + +#![crate::assert_run_order_module(17)] diff --git a/test_programs/compile_success_empty/attribute_order/src/main.nr b/test_programs/compile_success_empty/attribute_order/src/main.nr new file mode 100644 index 00000000000..9d5ba32b58e --- /dev/null +++ b/test_programs/compile_success_empty/attribute_order/src/main.nr @@ -0,0 +1,29 @@ +mod a; +mod b; + +#[assert_run_order_function(18)] +fn main() { + assert_eq(attributes_run, 19); +} + +comptime mut global attributes_run: Field = 0; + +pub comptime fn assert_run_order_function(_f: FunctionDefinition, order: Field) { + assert_eq(order, attributes_run); + attributes_run += 1; +} + +pub comptime fn assert_run_order_struct(_s: StructDefinition, order: Field) { + assert_eq(order, attributes_run); + attributes_run += 1; +} + +pub comptime fn assert_run_order_trait(_t: TraitDefinition, order: Field) { + assert_eq(order, attributes_run); + attributes_run += 1; +} + +pub comptime fn assert_run_order_module(_m: Module, order: Field) { + assert_eq(order, attributes_run); + attributes_run += 1; +} diff --git a/test_programs/compile_success_empty/attribute_sees_result_of_previous_attribute/Nargo.toml b/test_programs/compile_success_empty/attribute_sees_result_of_previous_attribute/Nargo.toml new file mode 100644 index 00000000000..ad71067a58f --- /dev/null +++ b/test_programs/compile_success_empty/attribute_sees_result_of_previous_attribute/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "attribute_sees_results_of_previous_attribute" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/attribute_sees_result_of_previous_attribute/src/main.nr b/test_programs/compile_success_empty/attribute_sees_result_of_previous_attribute/src/main.nr new file mode 100644 index 00000000000..561c3e12e0c --- /dev/null +++ b/test_programs/compile_success_empty/attribute_sees_result_of_previous_attribute/src/main.nr @@ -0,0 +1,11 @@ +#[derive(Eq)] +pub struct Foo {} + +#[check_eq_derived_for_foo] +fn main() {} + +comptime fn check_eq_derived_for_foo(_f: FunctionDefinition) { + let foo = quote {Foo}.as_type(); + let eq = quote {Eq}.as_trait_constraint(); + assert(foo.implements(eq)); +} diff --git a/test_programs/compile_success_empty/attributes_multiple/Nargo.toml b/test_programs/compile_success_empty/attributes_multiple/Nargo.toml new file mode 100644 index 00000000000..78b0e5b7b18 --- /dev/null +++ b/test_programs/compile_success_empty/attributes_multiple/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "attributes_multiple" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/attributes_multiple/src/main.nr b/test_programs/compile_success_empty/attributes_multiple/src/main.nr new file mode 100644 index 00000000000..aadfe5caf3c --- /dev/null +++ b/test_programs/compile_success_empty/attributes_multiple/src/main.nr @@ -0,0 +1,7 @@ +fn main() { + another_func() +} + +#['aztec(private)] +#['internal] +fn another_func() {} diff --git a/test_programs/compile_success_empty/attributes_struct/Nargo.toml b/test_programs/compile_success_empty/attributes_struct/Nargo.toml new file mode 100644 index 00000000000..e05ccb8d925 --- /dev/null +++ b/test_programs/compile_success_empty/attributes_struct/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "attributes_struct" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/attributes_struct/src/main.nr b/test_programs/compile_success_empty/attributes_struct/src/main.nr new file mode 100644 index 00000000000..713e6321f4b --- /dev/null +++ b/test_programs/compile_success_empty/attributes_struct/src/main.nr @@ -0,0 +1,22 @@ +#['some_attribute] +#['another_attribute] +pub struct SomeStruct { + a: Field, + b: Field, +} + +fn main() {} + +// Check that add_attribute and has_named_attribute work well + +#[abi(something)] +#[add_attribute] +pub struct Foo {} + +comptime fn add_attribute(s: StructDefinition) { + assert(!s.has_named_attribute("foo")); + s.add_attribute("foo"); + assert(s.has_named_attribute("foo")); + + assert(s.has_named_attribute("abi")); +} diff --git a/test_programs/compile_success_empty/auto_deref/Nargo.toml b/test_programs/compile_success_empty/auto_deref/Nargo.toml new file mode 100644 index 00000000000..ed2a51c0fb0 --- /dev/null +++ b/test_programs/compile_success_empty/auto_deref/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "auto_deref" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/auto_deref/src/main.nr b/test_programs/compile_success_empty/auto_deref/src/main.nr new file mode 100644 index 00000000000..d69aff7e0d4 --- /dev/null +++ b/test_programs/compile_success_empty/auto_deref/src/main.nr @@ -0,0 +1,7 @@ +fn main() { + let a = &mut &mut &mut [1, 2, 3]; + assert(a[0] == 1); + + a[0] = 4; + assert(a[0] == 4); +} diff --git a/test_programs/compile_success_empty/brillig_cast/Nargo.toml b/test_programs/compile_success_empty/brillig_cast/Nargo.toml new file mode 100644 index 00000000000..cb5a7f3f2bd --- /dev/null +++ b/test_programs/compile_success_empty/brillig_cast/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_cast" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/brillig_cast/src/main.nr b/test_programs/compile_success_empty/brillig_cast/src/main.nr new file mode 100644 index 00000000000..d7d0b1b8fa5 --- /dev/null +++ b/test_programs/compile_success_empty/brillig_cast/src/main.nr @@ -0,0 +1,44 @@ +// Tests a very simple Brillig function. +// +// The features being tested are cast operations on brillig +fn main() { + /// Safety: testing context + unsafe { + bool_casts(); + field_casts(); + uint_casts(); + int_casts(); + mixed_casts(); + } +} + +unconstrained fn bool_casts() { + assert(false == 0 as bool); + assert(true == 1 as bool); + assert(true == 3 as bool); +} + +unconstrained fn field_casts() { + assert(5 as u8 as Field == 5); + assert(256 as u8 as Field == 0); +} + +unconstrained fn uint_casts() { + let x: u32 = 300; + assert(x as u8 == 44); + assert(x as u32 == 300); + assert(x as u64 == 300); +} + +unconstrained fn int_casts() { + let x: i32 = 456; + assert(x as i8 == -56 as i8); + assert(x as i64 == 456); +} + +unconstrained fn mixed_casts() { + assert(100 as u32 as i32 as u32 == 100); + assert(257 as u8 as u32 == 1); + assert(1 as u8 as bool == true); + assert(true as i8 == 1); +} diff --git a/test_programs/compile_success_empty/brillig_field_binary_operations/Nargo.toml b/test_programs/compile_success_empty/brillig_field_binary_operations/Nargo.toml new file mode 100644 index 00000000000..fb17e881f4c --- /dev/null +++ b/test_programs/compile_success_empty/brillig_field_binary_operations/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_field_binary_operations" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/brillig_field_binary_operations/src/main.nr b/test_programs/compile_success_empty/brillig_field_binary_operations/src/main.nr new file mode 100644 index 00000000000..f55beb6d1a8 --- /dev/null +++ b/test_programs/compile_success_empty/brillig_field_binary_operations/src/main.nr @@ -0,0 +1,28 @@ +// Tests arithmetic operations on fields +fn main() { + /// Safety: testing context + unsafe { + let x = 4; + let y = 2; + assert((x + y) == add(x, y)); + assert((x - y) == sub(x, y)); + assert((x * y) == mul(x, y)); + assert((x / y) == div(x, y)); + } +} + +unconstrained fn add(x: Field, y: Field) -> Field { + x + y +} + +unconstrained fn sub(x: Field, y: Field) -> Field { + x - y +} + +unconstrained fn mul(x: Field, y: Field) -> Field { + x * y +} + +unconstrained fn div(x: Field, y: Field) -> Field { + x / y +} diff --git a/test_programs/compile_success_empty/brillig_integer_binary_operations/Nargo.toml b/test_programs/compile_success_empty/brillig_integer_binary_operations/Nargo.toml new file mode 100644 index 00000000000..cd550ce0252 --- /dev/null +++ b/test_programs/compile_success_empty/brillig_integer_binary_operations/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_integer_binary_operations" +type = "bin" +authors = [""] + +[dependencies] 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 new file mode 100644 index 00000000000..0e00f25e5bb --- /dev/null +++ b/test_programs/compile_success_empty/brillig_integer_binary_operations/src/main.nr @@ -0,0 +1,80 @@ +// Tests arithmetic operations on integers +fn main() { + let x: u32 = 6; + let y: u32 = 2; + + /// Safety: testing context + unsafe { + assert((x + y) == add(x, y)); + + assert((x - y) == sub(x, y)); + + assert((x * y) == mul(x, y)); + + assert((x / y) == div(x, y)); + // TODO SSA => ACIR has some issues with i32 ops + assert(check_signed_div(6, 2, 3)); + + assert(eq(1, 2) == false); + assert(eq(1, 1)); + + assert(lt(x, y) == false); + assert(lt(y, x)); + + assert((x & y) == and(x, y)); + assert((x | y) == or(x, y)); + // TODO SSA => ACIR has some issues with xor ops + assert(check_xor(x, y, 4)); + assert((x >> y as u8) == shr(x, y as u8)); + assert((x << y as u8) == shl(x, y as u8)); + } +} + +unconstrained fn add(x: u32, y: u32) -> u32 { + x + y +} + +unconstrained fn sub(x: u32, y: u32) -> u32 { + x - y +} + +unconstrained fn mul(x: u32, y: u32) -> u32 { + x * y +} + +unconstrained fn div(x: u32, y: u32) -> u32 { + x / y +} + +unconstrained fn check_signed_div(x: i32, y: i32, result: i32) -> bool { + (x / y) == result +} + +unconstrained fn eq(x: u32, y: u32) -> bool { + x == y +} + +unconstrained fn lt(x: u32, y: u32) -> bool { + x < y +} + +unconstrained fn and(x: u32, y: u32) -> u32 { + x & y +} + +unconstrained fn or(x: u32, y: u32) -> u32 { + x | y +} + +unconstrained fn check_xor(x: u32, y: u32, result: u32) -> bool { + (x ^ y) == result +} + +unconstrained fn shr(x: u32, y: u8) -> u32 { + x >> y +} + +unconstrained fn shl(x: u32, y: u8) -> u32 { + x << y +} + diff --git a/test_programs/compile_success_empty/brillig_modulo/Nargo.toml b/test_programs/compile_success_empty/brillig_modulo/Nargo.toml new file mode 100644 index 00000000000..7bac4a06607 --- /dev/null +++ b/test_programs/compile_success_empty/brillig_modulo/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_modulo" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/brillig_modulo/src/main.nr b/test_programs/compile_success_empty/brillig_modulo/src/main.nr new file mode 100644 index 00000000000..841d7d2dfca --- /dev/null +++ b/test_programs/compile_success_empty/brillig_modulo/src/main.nr @@ -0,0 +1,30 @@ +// Tests a very simple program. +// +// The features being tested is modulo operations on brillig +fn main() { + /// Safety: testing context + unsafe { + assert(modulo(47, 3) == 2); + assert(modulo(2, 3) == 2); + assert(signed_modulo(5, 3) == 2); + assert(signed_modulo(2, 3) == 2); + + let minus_two: i8 = -2; // 254 + let minus_three: i8 = -3; // 253 + let minus_five: i8 = -5; // 251 + // (5 / -3) * -3 + 2 = -1 * -3 + 2 = 3 + 2 = 5 + assert(signed_modulo(5, minus_three) == 2); + // (-5 / 3) * 3 - 2 = -1 * 3 - 2 = -3 - 2 = -5 + assert(signed_modulo(minus_five, 3) == minus_two); + // (-5 / -3) * -3 - 2 = 1 * -3 - 2 = -3 - 2 = -5 + assert(signed_modulo(minus_five, minus_three) == minus_two); + } +} + +unconstrained fn modulo(x: u32, y: u32) -> u32 { + x % y +} + +unconstrained fn signed_modulo(x: i8, y: i8) -> i8 { + x % y +} diff --git a/test_programs/compile_success_empty/brillig_slice_input/Nargo.toml b/test_programs/compile_success_empty/brillig_slice_input/Nargo.toml new file mode 100644 index 00000000000..a1c8cc3242b --- /dev/null +++ b/test_programs/compile_success_empty/brillig_slice_input/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_slice_input" +type = "bin" +authors = [""] + +[dependencies] 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..c43c5fae162 --- /dev/null +++ b/test_programs/compile_success_empty/brillig_slice_input/src/main.nr @@ -0,0 +1,31 @@ +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 }]); + /// Safety: testing context + unsafe { + 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 }]); + /// Safety: testing context + unsafe { + let brillig_sum = sum_slice(slice); + assert_eq(brillig_sum, 100); + } +} diff --git a/test_programs/compile_success_empty/cast_and_shift_global/Nargo.toml b/test_programs/compile_success_empty/cast_and_shift_global/Nargo.toml new file mode 100644 index 00000000000..92af6ed8333 --- /dev/null +++ b/test_programs/compile_success_empty/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_success_empty/cast_and_shift_global/src/main.nr b/test_programs/compile_success_empty/cast_and_shift_global/src/main.nr new file mode 100644 index 00000000000..2c0158fc71a --- /dev/null +++ b/test_programs/compile_success_empty/cast_and_shift_global/src/main.nr @@ -0,0 +1,8 @@ +global THREE: u32 = 3; +global EIGHT: u32 = 1 << THREE as u8; +global SEVEN: u32 = EIGHT - 1; + +fn main() { + assert([0; EIGHT] == [0; 8]); + assert([0; SEVEN] == [0; 7]); +} diff --git a/test_programs/compile_success_empty/check_large_field_bits/Nargo.toml b/test_programs/compile_success_empty/check_large_field_bits/Nargo.toml new file mode 100644 index 00000000000..33d5dd66484 --- /dev/null +++ b/test_programs/compile_success_empty/check_large_field_bits/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "check_large_field_bits" +type = "bin" +authors = [""] +compiler_version = ">=0.35.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/check_large_field_bits/src/main.nr b/test_programs/compile_success_empty/check_large_field_bits/src/main.nr new file mode 100644 index 00000000000..8022ea138ed --- /dev/null +++ b/test_programs/compile_success_empty/check_large_field_bits/src/main.nr @@ -0,0 +1,51 @@ +// 2^32 + 1 +global A: Field = 4294967297; +global B: Field = 4294967297; + +// 2^33 + 2 +global C: Field = A + B; + +fn main() { + // 2 * (2^32 + 1) == 2^33 + 2 + assert(C == 8589934594); + + let mut leading_zeroes = 0; + let mut stop = false; + let bits: [u1; 64] = C.to_be_bits(); + for i in 0..64 { + if (bits[i] == 0) & !stop { + leading_zeroes += 1; + } else { + stop = true; + } + } + let size = 64 - leading_zeroes; + + // 8589934594 has 34 bits + assert(size == 34); + C.assert_max_bit_size::<34>(); + + assert( + C.to_be_bits() + == [ + 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, 1, 0, + ], + ); + + // leading big-endian bits past 34 are 0's + assert( + C.to_be_bits() + == [ + 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, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, + ], + ); + assert( + C.to_be_bits() + == [ + 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, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, + ], + ); +} diff --git a/test_programs/compile_success_empty/checked_transmute/Nargo.toml b/test_programs/compile_success_empty/checked_transmute/Nargo.toml new file mode 100644 index 00000000000..f3392ec79bb --- /dev/null +++ b/test_programs/compile_success_empty/checked_transmute/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "checked_transmute" +type = "bin" +authors = [""] +compiler_version = ">=0.35.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/checked_transmute/src/main.nr b/test_programs/compile_success_empty/checked_transmute/src/main.nr new file mode 100644 index 00000000000..1acf07e98a8 --- /dev/null +++ b/test_programs/compile_success_empty/checked_transmute/src/main.nr @@ -0,0 +1,17 @@ +use std::mem::checked_transmute; + +fn main() { + // 1*(2 + 3) = 1*2 + 1*3 = 5 + let _: [Field; 5] = distribute::<1, 2, 3>([1, 2, 3, 4, 5]); +} + +pub fn distribute( + x: [Field; N * (A + B)], +) -> [Field; N * A + N * B] { + // asserts: [Field; N * (A + B)] = [Field; N * A + N * B] + // -> N * A + B = N * A + N * B + // + // This assert occurs during monomorphization when the actual values for N, A, and B + // become known. This also means if this function is not called, the assert will not trigger. + checked_transmute(x) +} diff --git a/test_programs/compile_success_empty/closure_explicit_types/Nargo.toml b/test_programs/compile_success_empty/closure_explicit_types/Nargo.toml new file mode 100644 index 00000000000..86ddff27910 --- /dev/null +++ b/test_programs/compile_success_empty/closure_explicit_types/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "closure_explicit_types" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/closure_explicit_types/src/main.nr b/test_programs/compile_success_empty/closure_explicit_types/src/main.nr new file mode 100644 index 00000000000..c43fc9cb34b --- /dev/null +++ b/test_programs/compile_success_empty/closure_explicit_types/src/main.nr @@ -0,0 +1,71 @@ +fn ret_normal_lambda1() -> fn() -> Field { + || 10 +} +// return lamda that captures a thing +fn ret_closure1() -> fn[(Field,)]() -> Field { + let x = 20; + || x + 10 +} +// return lamda that captures two things +fn ret_closure2() -> fn[(Field, Field)]() -> Field { + let x = 20; + let y = 10; + || x + y + 10 +} +// return lamda that captures two things with different types +fn ret_closure3() -> fn[(u32, u64)]() -> u64 { + let x: u32 = 20; + let y: u64 = 10; + || x as u64 + y + 10 +} +// accepts closure that has 1 thing in its env, calls it and returns the result +fn accepts_closure1(f: fn[(Field,)]() -> Field) -> Field { + f() +} +// accepts closure that has 1 thing in its env and returns it +fn accepts_closure2(f: fn[(Field,)]() -> Field) -> fn[(Field,)]() -> Field { + f +} +// accepts closure with different types in the capture group +fn accepts_closure3(f: fn[(u32, u64)]() -> u64) -> u64 { + f() +} +// generic over closure environments +fn add_results(f1: fn[Env1]() -> Field, f2: fn[Env2]() -> Field) -> Field { + f1() + f2() +} +// a *really* generic function +fn map(arr: [T; N], f: fn[Env](T) -> U) -> [U; N] { + let first_elem = f(arr[0]); + let mut ret = [first_elem; N]; + + for i in 1..N { + ret[i] = f(arr[i]); + } + + ret +} + +fn main() { + assert(ret_normal_lambda1()() == 10); + assert(ret_closure1()() == 30); + assert(ret_closure2()() == 40); + assert(ret_closure3()() == 40); + + let x = 50; + assert(accepts_closure1(|| x) == 50); + assert(accepts_closure2(|| x + 10)() == 60); + + let y: u32 = 30; + let z: u64 = 40; + assert(accepts_closure3(|| y as u64 + z) == 70); + + let w = 50; + assert(add_results(|| 100, || x) == 150); + assert(add_results(|| x + 100, || w + x) == 250); + + let arr = [1, 2, 3, 4]; + + assert(map(arr, |n| n + 1) == [2, 3, 4, 5]); + assert(map(arr, |n| n + x) == [51, 52, 53, 54]); +} diff --git a/test_programs/compile_success_empty/comptime_apply_range_constraint/Nargo.toml b/test_programs/compile_success_empty/comptime_apply_range_constraint/Nargo.toml new file mode 100644 index 00000000000..84d16060440 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_apply_range_constraint/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "comptime_apply_range_constraint" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_apply_range_constraint/src/main.nr b/test_programs/compile_success_empty/comptime_apply_range_constraint/src/main.nr new file mode 100644 index 00000000000..ff5e0ba9511 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_apply_range_constraint/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + comptime { + 2.assert_max_bit_size::<8>() + } +} diff --git a/test_programs/compile_success_empty/comptime_array_len/Nargo.toml b/test_programs/compile_success_empty/comptime_array_len/Nargo.toml new file mode 100644 index 00000000000..c07deddc6c5 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_array_len/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "comptime_array_len" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_array_len/src/main.nr b/test_programs/compile_success_empty/comptime_array_len/src/main.nr new file mode 100644 index 00000000000..283f3ea8d3e --- /dev/null +++ b/test_programs/compile_success_empty/comptime_array_len/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + comptime { + assert_eq([1, 2, 3].len(), 3); + } +} diff --git a/test_programs/compile_success_empty/comptime_as_field/Nargo.toml b/test_programs/compile_success_empty/comptime_as_field/Nargo.toml new file mode 100644 index 00000000000..294832ba329 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_as_field/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "comptime_as_field" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_as_field/src/main.nr b/test_programs/compile_success_empty/comptime_as_field/src/main.nr new file mode 100644 index 00000000000..e13db54b80b --- /dev/null +++ b/test_programs/compile_success_empty/comptime_as_field/src/main.nr @@ -0,0 +1,6 @@ +fn main() { + comptime { + let _: U128 = U128::from_integer(1); + } +} + diff --git a/test_programs/compile_success_empty/comptime_as_slice/Nargo.toml b/test_programs/compile_success_empty/comptime_as_slice/Nargo.toml new file mode 100644 index 00000000000..90c67b07b2b --- /dev/null +++ b/test_programs/compile_success_empty/comptime_as_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/compile_success_empty/comptime_as_slice/src/main.nr b/test_programs/compile_success_empty/comptime_as_slice/src/main.nr new file mode 100644 index 00000000000..bc3f649e52a --- /dev/null +++ b/test_programs/compile_success_empty/comptime_as_slice/src/main.nr @@ -0,0 +1,8 @@ +fn main() { + comptime { + let ws: [Field; 3] = [1; 3]; + let ws_as_slice: [Field] = ws.as_slice(); + + assert_eq(ws[0], ws_as_slice[0]); + } +} diff --git a/test_programs/compile_success_empty/comptime_change_type_each_iteration/Nargo.toml b/test_programs/compile_success_empty/comptime_change_type_each_iteration/Nargo.toml new file mode 100644 index 00000000000..38e72395bb5 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_change_type_each_iteration/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_change_type_each_iteration" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_change_type_each_iteration/src/main.nr b/test_programs/compile_success_empty/comptime_change_type_each_iteration/src/main.nr new file mode 100644 index 00000000000..153eb308911 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_change_type_each_iteration/src/main.nr @@ -0,0 +1,20 @@ +use std::meta::ctstring::AsCtString; + +fn main() { + comptime { + for i in 9..11 { + // Lengths are different on each iteration: + // foo9, foo10 + let name = f"foo{i}".as_ctstring().as_quoted_str!(); + + // So to call `from_signature` we need to delay the type check + // by quoting the function call so that we re-typecheck on each iteration + let hash = std::meta::unquote!(quote { from_signature($name) }); + assert(hash > 3); + } + } +} + +fn from_signature(_signature: str) -> u32 { + N +} diff --git a/test_programs/compile_success_empty/comptime_closures/Nargo.toml b/test_programs/compile_success_empty/comptime_closures/Nargo.toml new file mode 100644 index 00000000000..50cde2ec2dd --- /dev/null +++ b/test_programs/compile_success_empty/comptime_closures/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_closures" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_closures/src/main.nr b/test_programs/compile_success_empty/comptime_closures/src/main.nr new file mode 100644 index 00000000000..e8a0366a304 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_closures/src/main.nr @@ -0,0 +1,32 @@ +fn main() { + comptime { + closure_test(0); + } +} + +fn closure_test(mut x: Field) { + let one = 1; + let add1 = |z| (|| { *z += one; })(); + + let two = 2; + let add2 = |z| { *z = *z + two; }; + + add1(&mut x); + assert(x == 1); + + add2(&mut x); + assert(x == 3); + + issue_2120(); +} + +fn issue_2120() { + let x1 = &mut 42; + let set_x1 = |y| { *x1 = y; }; + + assert(*x1 == 42); + set_x1(44); + assert(*x1 == 44); + set_x1(*x1); + assert(*x1 == 44); +} diff --git a/test_programs/compile_success_empty/comptime_derive_generators/Nargo.toml b/test_programs/compile_success_empty/comptime_derive_generators/Nargo.toml new file mode 100644 index 00000000000..0bf7ca9d0f2 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_derive_generators/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_derive_generators" +type = "bin" +authors = [""] +compiler_version = ">=0.35.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_derive_generators/src/main.nr b/test_programs/compile_success_empty/comptime_derive_generators/src/main.nr new file mode 100644 index 00000000000..b79ce9956c1 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_derive_generators/src/main.nr @@ -0,0 +1,67 @@ +use std::embedded_curve_ops::EmbeddedCurvePoint; + +fn main() { + comptime { + // Result computed from executing `derive_generators` with non-comptime Noir + let result = [ + EmbeddedCurvePoint { + x: 0x0224a8abc6c8b8d50373d64cd2a1ab1567bf372b3b1f7b861d7f01257052d383, + y: 0x2358629b90eafb299d6650a311e79914b0215eb0a790810b26da5a826726d711, + is_infinite: false, + }, + EmbeddedCurvePoint { + x: 0x0f106f6d46bc904a5290542490b2f238775ff3c445b2f8f704c466655f460a2a, + y: 0x29ab84d472f1d33f42fe09c47b8f7710f01920d6155250126731e486877bcf27, + is_infinite: false, + }, + EmbeddedCurvePoint { + x: 0x0298f2e42249f0519c8a8abd91567ebe016e480f219b8c19461d6a595cc33696, + y: 0x035bec4b8520a4ece27bd5aafabee3dfe1390d7439c419a8c55aceb207aac83b, + is_infinite: false, + }, + EmbeddedCurvePoint { + x: 0x2c9628479de4181ea77e7b0913ccf41d2a74155b1d9c82eaa220c218781f6f3b, + y: 0x278f86b8fd95520b5da23bee1a5e354dc5dcb0cb43d6b76e628ddbffb101d776, + is_infinite: false, + }, + EmbeddedCurvePoint { + x: 0x0be1916f382e3532aa53a766fe74b1a983784caab90290aea7bf616bc371fb41, + y: 0x0f65545005e896f14249956344faf9addd762b7573a487b58f805a361d920a20, + is_infinite: false, + }, + EmbeddedCurvePoint { + x: 0x29ff8437ae5bec89981441b23036a22b7fd5bee9eff0e83c0dd5b87bfb5bd60e, + y: 0x1fd247352b77e2676b22db23cf7cd482474f543e3480b5a39c42f839a306be10, + is_infinite: false, + }, + EmbeddedCurvePoint { + x: 0x2f3bd4e98f8c8458cd58888749f0f5e582a43565767398e08e50e94b9b19a4d9, + y: 0x1f534906d1aa8b4ba74ad9e3f85ae3f8295e51eaafd15b5d116801b96360205b, + is_infinite: false, + }, + EmbeddedCurvePoint { + x: 0x27759098f425b76447c2c52728576803a1ac5de37bba875ac47cdcff539ab931, + y: 0x0aa47ee64d12d856cfb81b595c1d60ceecb693f0fdae644746ff333e39f61db7, + is_infinite: false, + }, + EmbeddedCurvePoint { + x: 0x015ca8d68616fde86c9108e3db04f588e0f308e60d367e963b7d460fe9a65e6c, + y: 0x2cf918009dda942ac9d59903cd2d0294d8738f938b1394170d892a027d0f347b, + is_infinite: false, + }, + EmbeddedCurvePoint { + x: 0x0d1783d5b256765515f3c9988df9f1ba7e6f5fb0248c8971fbc503ffd5187714, + y: 0x2ebb434ff4857fc3621f3bc3c6b8002b17d02d9c204e75f19b8f0b99ea68402c, + is_infinite: false, + }, + ]; + + let generators: [EmbeddedCurvePoint; 10] = + std::hash::derive_generators("DEFAULT_DOMAIN_SEPARATOR".as_bytes(), 5); + + for i in 0..10 { + assert(generators[i].x == result[i].x); + assert(generators[i].y == result[i].y); + } + } +} diff --git a/test_programs/compile_success_empty/comptime_fmt_strings/Nargo.toml b/test_programs/compile_success_empty/comptime_fmt_strings/Nargo.toml new file mode 100644 index 00000000000..84162d3c093 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_fmt_strings/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_fmt_strings" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_fmt_strings/src/main.nr b/test_programs/compile_success_empty/comptime_fmt_strings/src/main.nr new file mode 100644 index 00000000000..8cdd15aaa0e --- /dev/null +++ b/test_programs/compile_success_empty/comptime_fmt_strings/src/main.nr @@ -0,0 +1,29 @@ +fn main() { + // format strings are lowered as normal strings + let (s1, s2): (str<39>, str<4>) = comptime { + let x = 4; + let y = 5; + + // Can't print these at compile-time here since printing to stdout while + // compiling breaks the test runner. + let s1 = f"x is {x}, fake interpolation: {{y}}, y is {y}"; + let s2 = std::mem::zeroed::>(); + (s1, s2) + }; + assert_eq(s1, "x is 4, fake interpolation: {y}, y is 5"); + assert_eq(s2, "\0\0\0\0"); + + // Mainly test fmtstr::quoted_contents + call!(glue(quote { hello }, quote { world })); +} + +comptime fn glue(x: Quoted, y: Quoted) -> Quoted { + f"{x}_{y}".quoted_contents() +} + +fn hello_world() {} + +comptime fn call(x: Quoted) -> Quoted { + quote { $x() } +} + diff --git a/test_programs/compile_success_empty/comptime_from_field/Nargo.toml b/test_programs/compile_success_empty/comptime_from_field/Nargo.toml new file mode 100644 index 00000000000..38a46ba0dbe --- /dev/null +++ b/test_programs/compile_success_empty/comptime_from_field/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "comptime_from_field" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_from_field/src/main.nr b/test_programs/compile_success_empty/comptime_from_field/src/main.nr new file mode 100644 index 00000000000..722c5c7eb32 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_from_field/src/main.nr @@ -0,0 +1,6 @@ +fn main() { + comptime { + let _: Field = U128::from_hex("0x0").to_integer(); + } +} + diff --git a/test_programs/compile_success_empty/comptime_function_definition/Nargo.toml b/test_programs/compile_success_empty/comptime_function_definition/Nargo.toml new file mode 100644 index 00000000000..a5f1e75dcef --- /dev/null +++ b/test_programs/compile_success_empty/comptime_function_definition/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_function_definition" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_function_definition/src/main.nr b/test_programs/compile_success_empty/comptime_function_definition/src/main.nr new file mode 100644 index 00000000000..105c1e8d577 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_function_definition/src/main.nr @@ -0,0 +1,107 @@ +use std::meta::type_of; + +pub struct Foo { + x: Field, + field: Field, +} + +#[function_attr] +pub fn foo( + w: i32, + y: Field, + Foo { x, field: some_field }: Foo, + mut a: bool, + (b, c): (i32, i32), +) -> i32 { + let _ = (w, y, x, some_field, a, b, c); + 1 +} + +#[test] +#[deprecated] +#[check_named_attribute] +fn some_test() {} + +comptime fn function_attr(f: FunctionDefinition) { + // Check FunctionDefinition::parameters + let parameters = f.parameters(); + assert_eq(parameters.len(), 5); + + assert_eq(parameters[0].0, quote { w }); + assert_eq(parameters[1].0, quote { y }); + assert_eq(parameters[2].0, quote { Foo { x, field: some_field } }); + assert_eq(parameters[3].0, quote { mut a }); + assert_eq(parameters[4].0, quote { (b, c) }); + + let an_i32: i32 = 0; + + assert_eq(parameters[0].1, type_of(an_i32)); + assert_eq(parameters[1].1, type_of(0)); + assert_eq(parameters[2].1, type_of(Foo { x: 0, field: 1 })); + assert_eq(parameters[3].1, type_of(true)); + assert_eq(parameters[4].1, type_of((an_i32, an_i32))); + + // Check FunctionDefinition::return_type + assert_eq(f.return_type(), type_of(an_i32)); + + // Check FunctionDefinition::name + assert_eq(f.name(), quote { foo }); + + assert(f.has_named_attribute("function_attr")); +} + +comptime fn check_named_attribute(f: FunctionDefinition) { + assert(f.has_named_attribute("test")); + assert(f.has_named_attribute("deprecated")); +} + +#[mutate_add_one] +fn add_one() {} + +comptime fn mutate_add_one(f: FunctionDefinition) { + // fn add_one(x: Field) + assert_eq(f.parameters().len(), 0); + f.set_parameters(&[(quote { x }, type_of(0))]); + assert_eq(f.parameters().len(), 1); + + // fn add_one(x: Field) -> Field + assert_eq(f.return_type(), type_of(())); + f.set_return_type(type_of(0)); + assert_eq(f.return_type(), type_of(0)); + + // fn add_one(x: Field) -> Field { x + 1 } + f.set_body(quote { x + 1 }.as_expr().unwrap()); +} + +fn main() { + assert_eq(add_one(41), 42); +} + +contract some_contract { + // No pub on the return type is an error + #[super::set_pub_return] + pub fn bar() -> Field { + 1 + } +} + +comptime fn set_pub_return(f: FunctionDefinition) { + f.set_return_public(true); +} + +mod foo { + #[attr] + pub fn some() {} + + comptime fn attr(f: FunctionDefinition) { + assert_eq(f.module().name(), quote { foo }); + + assert(!f.is_unconstrained()); + + f.set_unconstrained(true); + assert(f.is_unconstrained()); + + f.set_unconstrained(false); + assert(!f.is_unconstrained()); + } +} diff --git a/test_programs/compile_success_empty/comptime_global_using_trait/Nargo.toml b/test_programs/compile_success_empty/comptime_global_using_trait/Nargo.toml new file mode 100644 index 00000000000..2de6e4d149e --- /dev/null +++ b/test_programs/compile_success_empty/comptime_global_using_trait/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_global_using_trait" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_global_using_trait/src/main.nr b/test_programs/compile_success_empty/comptime_global_using_trait/src/main.nr new file mode 100644 index 00000000000..86bde1c5eba --- /dev/null +++ b/test_programs/compile_success_empty/comptime_global_using_trait/src/main.nr @@ -0,0 +1,3 @@ +pub comptime global FOO: i32 = Default::default(); + +fn main() {} diff --git a/test_programs/compile_success_empty/comptime_globals_regression/Nargo.toml b/test_programs/compile_success_empty/comptime_globals_regression/Nargo.toml new file mode 100644 index 00000000000..5c5b64c712a --- /dev/null +++ b/test_programs/compile_success_empty/comptime_globals_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_globals_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_globals_regression/src/main.nr b/test_programs/compile_success_empty/comptime_globals_regression/src/main.nr new file mode 100644 index 00000000000..45afef6d831 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_globals_regression/src/main.nr @@ -0,0 +1,17 @@ +comptime mut global COUNTER: Field = 0; + +fn main() { + comptime { increment() }; + comptime { increment() }; + + assert_eq(get_counter(), 2); +} + +fn get_counter() -> Field { + COUNTER +} + +comptime fn increment() { + COUNTER += 1; + assert_eq(get_counter(), COUNTER); +} diff --git a/test_programs/compile_success_empty/comptime_keccak/Nargo.toml b/test_programs/compile_success_empty/comptime_keccak/Nargo.toml new file mode 100644 index 00000000000..47c8654804d --- /dev/null +++ b/test_programs/compile_success_empty/comptime_keccak/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_keccak" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_keccak/src/main.nr b/test_programs/compile_success_empty/comptime_keccak/src/main.nr new file mode 100644 index 00000000000..dc4e88b7ab2 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_keccak/src/main.nr @@ -0,0 +1,32 @@ +// Tests a very simple program. +// +// The features being tested is keccak256 in brillig +fn main() { + comptime { + let x = 0xbd; + let result = [ + 0x5a, 0x50, 0x2f, 0x9f, 0xca, 0x46, 0x7b, 0x26, 0x6d, 0x5b, 0x78, 0x33, 0x65, 0x19, + 0x37, 0xe8, 0x05, 0x27, 0x0c, 0xa3, 0xf3, 0xaf, 0x1c, 0x0d, 0xd2, 0x46, 0x2d, 0xca, + 0x4b, 0x3b, 0x1a, 0xbf, + ]; + // 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 = keccak256([x as u8], 1); + assert(digest == result); + //#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); + + assert(hash_a == hash_b); + + let message_size_big = 8; + let hash_c = keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); + + assert(hash_a != hash_c); + } +} + +comptime fn keccak256(data: [u8; N], msg_len: u32) -> [u8; 32] { + std::hash::keccak256(data, msg_len) +} diff --git a/test_programs/compile_success_empty/comptime_module/Nargo.toml b/test_programs/compile_success_empty/comptime_module/Nargo.toml new file mode 100644 index 00000000000..cb295ca1e17 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_module/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_module" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_module/src/main.nr b/test_programs/compile_success_empty/comptime_module/src/main.nr new file mode 100644 index 00000000000..20fd8053fbe --- /dev/null +++ b/test_programs/compile_success_empty/comptime_module/src/main.nr @@ -0,0 +1,127 @@ +#['outer_attribute] +mod foo { + #!['some_attribute] + pub fn x() {} + pub fn y() {} + pub fn z() {} + + pub struct Struct1 {} + pub struct Struct2 {} + pub struct Struct3 {} +} + +contract bar {} + +#['some_attribute] +mod another_module {} + +#[outer_attribute_func] +mod yet_another_module { + #![super::inner_attribute_func] + pub fn foo() {} +} + +#[outer_attribute_separate_module] +mod separate_module; + +comptime mut global counter: u32 = 0; + +comptime fn increment_counter() { + counter += 1; +} + +comptime fn outer_attribute_func(m: Module) -> Quoted { + assert_eq(m.name(), quote { yet_another_module }); + increment_counter(); + quote { pub fn generated_outer_function() {} } +} + +comptime fn inner_attribute_func(m: Module) -> Quoted { + assert_eq(m.name(), quote { yet_another_module }); + increment_counter(); + quote { pub fn generated_inner_function() {} } +} + +comptime fn outer_attribute_separate_module(m: Module) { + assert_eq(m.name(), quote { separate_module }); + increment_counter(); +} + +pub struct Foo {} + +#[add_function] +mod add_to_me { + fn add_to_me_function() {} +} + +comptime fn add_function(m: Module) { + m.add_item( + quote { pub fn added_function() -> super::Foo { + add_to_me_function(); + super::Foo {} + } }, + ); +} + +fn main() { + let _ = foo::Struct1 {}; + + comptime { + // Check Module::is_contract + let foo = quote { foo }.as_module().unwrap(); + assert(!foo.is_contract()); + + let bar = quote { bar }.as_module().unwrap(); + assert(bar.is_contract()); + + let another_module = quote { another_module }.as_module().unwrap(); + + // Check Module::functions + let foo_functions = foo.functions(); + assert_eq(foo_functions.len(), 3); + assert_eq(foo_functions[0].name(), quote { x }); + assert_eq(foo_functions[1].name(), quote { y }); + assert_eq(foo_functions[2].name(), quote { z }); + + assert_eq(bar.functions().len(), 0); + + // Check Module::structs + let foo_structs = foo.structs(); + assert_eq(foo_structs.len(), 3); + assert_eq(foo_structs[0].name(), quote { Struct1 }); + assert_eq(foo_structs[1].name(), quote { Struct2 }); + assert_eq(foo_structs[2].name(), quote { Struct3 }); + assert_eq(bar.structs().len(), 0); + + // Check Module::name + assert_eq(foo.name(), quote { foo }); + assert_eq(bar.name(), quote { bar }); + + // Check Module::has_named_attribute + assert(foo.has_named_attribute("some_attribute")); + assert(foo.has_named_attribute("outer_attribute")); + assert(!bar.has_named_attribute("some_attribute")); + assert(another_module.has_named_attribute("some_attribute")); + } + + assert_eq(counter, 4); + + yet_another_module::generated_outer_function(); + yet_another_module::generated_inner_function(); + + let _ = add_to_me::added_function(); +} + +// docs:start:as_module_example +mod baz { + pub mod qux {} +} + +#[test] +fn as_module_test() { + comptime { + let my_mod = quote { baz::qux }.as_module().unwrap(); + assert_eq(my_mod.name(), quote { qux }); + } +} +// docs:end:as_module_example diff --git a/test_programs/compile_success_empty/comptime_module/src/separate_module.nr b/test_programs/compile_success_empty/comptime_module/src/separate_module.nr new file mode 100644 index 00000000000..c1aeac4622c --- /dev/null +++ b/test_programs/compile_success_empty/comptime_module/src/separate_module.nr @@ -0,0 +1,6 @@ +#![inner_attribute_separate_module] + +comptime fn inner_attribute_separate_module(m: Module) { + assert_eq(m.name(), quote { separate_module }); + super::increment_counter(); +} 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..111968a8a41 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_mut_global/src/main.nr @@ -0,0 +1,28 @@ +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/comptime_parse_statement_as_expression/Nargo.toml b/test_programs/compile_success_empty/comptime_parse_statement_as_expression/Nargo.toml new file mode 100644 index 00000000000..65fa5b1ed06 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_parse_statement_as_expression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_parse_statement_as_expression" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_parse_statement_as_expression/src/main.nr b/test_programs/compile_success_empty/comptime_parse_statement_as_expression/src/main.nr new file mode 100644 index 00000000000..50e88382737 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_parse_statement_as_expression/src/main.nr @@ -0,0 +1,26 @@ +fn main() { + comptime { + let block = quote {{ + 1; + 2; + 3 + }}; + let statements = block.as_expr().unwrap().as_block().unwrap(); + let last = statements.pop_back().1; + + // `3` should fit in an expression position even though it is + // originally a StatementKind::Expression + let regression1 = quote {{ + let _ = $last; + }}; + assert(regression1.as_expr().is_some()); + + // `1;` should fit in an expression position even though it is + // originally a StatementKind::Semi + let first = statements.pop_front().0; + let regression2 = quote {{ + let _ = $first; + }}; + assert(regression2.as_expr().is_some()); + } +} diff --git a/test_programs/compile_success_empty/comptime_recursion_regression/Nargo.toml b/test_programs/compile_success_empty/comptime_recursion_regression/Nargo.toml new file mode 100644 index 00000000000..74710a6ac2a --- /dev/null +++ b/test_programs/compile_success_empty/comptime_recursion_regression/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "comptime_recursion_regression" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_recursion_regression/src/main.nr b/test_programs/compile_success_empty/comptime_recursion_regression/src/main.nr new file mode 100644 index 00000000000..0461fd9c4cb --- /dev/null +++ b/test_programs/compile_success_empty/comptime_recursion_regression/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: Field, y: Field) { + let flag = (x == 1) | (y == 2); + assert(flag | false == flag); +} diff --git a/test_programs/compile_success_empty/comptime_slice_equality/Nargo.toml b/test_programs/compile_success_empty/comptime_slice_equality/Nargo.toml new file mode 100644 index 00000000000..72700d87d8b --- /dev/null +++ b/test_programs/compile_success_empty/comptime_slice_equality/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_slice_equality" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_slice_equality/src/main.nr b/test_programs/compile_success_empty/comptime_slice_equality/src/main.nr new file mode 100644 index 00000000000..e39e1fe0fb8 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_slice_equality/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + comptime { + assert_eq(&[1], &[1]); + } +} diff --git a/test_programs/compile_success_empty/comptime_slice_methods/Nargo.toml b/test_programs/compile_success_empty/comptime_slice_methods/Nargo.toml new file mode 100644 index 00000000000..8ff281cf9e3 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_slice_methods/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_slice_methods" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_slice_methods/src/main.nr b/test_programs/compile_success_empty/comptime_slice_methods/src/main.nr new file mode 100644 index 00000000000..8341669a0a4 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_slice_methods/src/main.nr @@ -0,0 +1,26 @@ +fn main() { + comptime { + // Comptime scopes are counted as unconstrained + assert(std::runtime::is_unconstrained()); + + let slice = &[2]; + let slice = slice.push_back(3); + let slice = slice.push_front(1); + assert_eq(slice, &[1, 2, 3]); + + let slice = slice.insert(1, 10); + assert_eq(slice, &[1, 10, 2, 3]); + + let (slice, ten) = slice.remove(1); + assert_eq(slice, &[1, 2, 3]); + assert_eq(ten, 10); + + let (one, slice) = slice.pop_front(); + assert_eq(slice, &[2, 3]); + assert_eq(one, 1); + + let (slice, three) = slice.pop_back(); + assert_eq(slice, &[2]); + assert_eq(three, 3); + } +} diff --git a/test_programs/compile_success_empty/comptime_str_as_bytes/Nargo.toml b/test_programs/compile_success_empty/comptime_str_as_bytes/Nargo.toml new file mode 100644 index 00000000000..f387e0e393a --- /dev/null +++ b/test_programs/compile_success_empty/comptime_str_as_bytes/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_str_as_bytes" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_str_as_bytes/src/main.nr b/test_programs/compile_success_empty/comptime_str_as_bytes/src/main.nr new file mode 100644 index 00000000000..fe69f2205c7 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_str_as_bytes/src/main.nr @@ -0,0 +1,9 @@ +fn main() { + comptime { + let hello_world_string = "hello world"; + let hello_world_bytes: [u8; 11] = + [0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]; + + assert_eq(hello_world_string.as_bytes(), hello_world_bytes); + } +} diff --git a/test_programs/compile_success_empty/comptime_struct_definition/Nargo.toml b/test_programs/compile_success_empty/comptime_struct_definition/Nargo.toml new file mode 100644 index 00000000000..4495d27e028 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_struct_definition/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_struct_definition" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_struct_definition/src/main.nr b/test_programs/compile_success_empty/comptime_struct_definition/src/main.nr new file mode 100644 index 00000000000..75d48c6f1dd --- /dev/null +++ b/test_programs/compile_success_empty/comptime_struct_definition/src/main.nr @@ -0,0 +1,65 @@ +#[my_comptime_fn] +pub struct MyType { + field1: [A; 10], + field2: (B, C), +} + +#[mutate_struct_fields] +pub struct I32AndField { + z: i8, +} + +comptime fn my_comptime_fn(typ: StructDefinition) { + let _ = typ.as_type(); + assert_eq(typ.generics().len(), 3); + assert_eq(typ.fields_as_written().len(), 2); + assert_eq(typ.name(), quote { MyType }); +} + +comptime fn mutate_struct_fields(s: StructDefinition) { + let fields = &[(quote {x}, quote {i32}.as_type()), (quote {y}, quote {Field}.as_type())]; + s.set_fields(fields); +} + +mod foo { + #[attr] + pub struct Foo {} + + comptime fn attr(s: StructDefinition) { + assert_eq(s.module().name(), quote { foo }); + } + + #[add_generic] + pub struct Bar {} + + // docs:start:add-generic-example + comptime fn add_generic(s: StructDefinition) { + assert_eq(s.generics().len(), 0); + let new_generic = s.add_generic("T"); + + let generics = s.generics(); + assert_eq(generics.len(), 1); + assert_eq(generics[0], new_generic); + } + // docs:end:add-generic-example +} + +fn main() { + comptime { + let typ = quote { MyType }.as_type(); + let (struct_def, generics) = typ.as_struct().unwrap(); + + let fields = struct_def.fields(generics); + assert_eq(fields.len(), 2); + + let (field1_name, field1_type) = fields[0]; + let (field2_name, field2_type) = fields[1]; + + assert_eq(field1_name, quote { field1 }); + assert_eq(field2_name, quote { field2 }); + + // Ensure .fields(generics) actually performs substitutions on generics + assert_eq(field1_type, quote { [i8; 10] }.as_type()); + assert_eq(field2_type, quote { (i16, i32) }.as_type()); + } +} diff --git a/test_programs/compile_success_empty/comptime_to_radix/Nargo.toml b/test_programs/compile_success_empty/comptime_to_radix/Nargo.toml new file mode 100644 index 00000000000..35713aff805 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_to_radix/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "comptime_to_radix" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_to_radix/src/main.nr b/test_programs/compile_success_empty/comptime_to_radix/src/main.nr new file mode 100644 index 00000000000..2233436a46c --- /dev/null +++ b/test_programs/compile_success_empty/comptime_to_radix/src/main.nr @@ -0,0 +1,9 @@ +fn main() { + comptime { + let le_bytes: [u8; 3] = 257.to_le_bytes(); + assert_eq(le_bytes, [1, 1, 0]); + + let be_bytes: [u8; 3] = 257.to_be_bytes(); + assert_eq(be_bytes, [0, 1, 1]); + } +} diff --git a/test_programs/compile_success_empty/comptime_trait_constraint/Nargo.toml b/test_programs/compile_success_empty/comptime_trait_constraint/Nargo.toml new file mode 100644 index 00000000000..c7e28c053a7 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_trait_constraint/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_trait_constraint" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_trait_constraint/src/main.nr b/test_programs/compile_success_empty/comptime_trait_constraint/src/main.nr new file mode 100644 index 00000000000..39ac1b5cde1 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_trait_constraint/src/main.nr @@ -0,0 +1,38 @@ +use std::hash::{Hash, Hasher}; + +trait TraitWithGenerics { + fn foo(self) -> (A, B); +} + +fn main() { + comptime { + let constraint1 = quote { Default }.as_trait_constraint(); + let constraint2 = quote { TraitWithGenerics }.as_trait_constraint(); + + assert(constraint1 != constraint2); + + let mut hasher = TestHasher { result: 0 }; + constraint1.hash(&mut hasher); + let hash1 = hasher.finish(); + + let mut hasher = TestHasher { result: 0 }; + constraint2.hash(&mut hasher); + let hash2 = hasher.finish(); + + assert(hash1 != hash2); + } +} + +struct TestHasher { + result: Field, +} + +impl Hasher for TestHasher { + fn finish(self) -> Field { + self.result + } + + fn write(&mut self, input: Field) { + self.result += input; + } +} diff --git a/test_programs/compile_success_empty/comptime_trait_impl/Nargo.toml b/test_programs/compile_success_empty/comptime_trait_impl/Nargo.toml new file mode 100644 index 00000000000..c9a6f1e150e --- /dev/null +++ b/test_programs/compile_success_empty/comptime_trait_impl/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_trait_impl" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_trait_impl/src/main.nr b/test_programs/compile_success_empty/comptime_trait_impl/src/main.nr new file mode 100644 index 00000000000..598f04c5d3d --- /dev/null +++ b/test_programs/compile_success_empty/comptime_trait_impl/src/main.nr @@ -0,0 +1,27 @@ +trait SomeTrait { + fn foo(); +} +pub struct SomeStruct {} + +impl SomeTrait for SomeStruct { + fn foo() {} +} + +fn main() { + comptime { + let some_struct = quote { SomeStruct }.as_type(); + let some_trait = quote { SomeTrait }.as_trait_constraint(); + let trait_impl = some_struct.get_trait_impl(some_trait).unwrap(); + + // Check TraitImpl::trait_generic_args + let trait_generic_args = trait_impl.trait_generic_args(); + assert_eq(trait_generic_args.len(), 2); + assert_eq(trait_generic_args[0], quote { i32 }.as_type()); + assert_eq(trait_generic_args[1], quote { i64 }.as_type()); + + // Check TraitImpl::methods + let methods = trait_impl.methods(); + assert_eq(methods.len(), 1); + assert_eq(methods[0].name(), quote { foo }); + } +} diff --git a/test_programs/compile_success_empty/comptime_traits/Nargo.toml b/test_programs/compile_success_empty/comptime_traits/Nargo.toml new file mode 100644 index 00000000000..75df4dc5c20 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_traits/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_traits" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_traits/src/main.nr b/test_programs/compile_success_empty/comptime_traits/src/main.nr new file mode 100644 index 00000000000..11025d45024 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_traits/src/main.nr @@ -0,0 +1,34 @@ +use std::ops::Neg; + +fn main() { + comptime { + // impl Eq for Field + assert(3 == 3); + + // impl Default for [T; N] where T: Default + // impl Default for Field + let array = Default::default(); + + // impl Eq for [T; N] where T: Eq + // impl Eq for Field + assert([1, 2] != array); + } +} + +struct MyType { + value: i32, +} + +impl Neg for MyType { + fn neg(self) -> Self { + self + } +} + +pub fn neg_at_comptime() { + comptime { + let value = MyType { value: 1 }; + let _result = -value; + } +} + diff --git a/test_programs/compile_success_empty/comptime_type/Nargo.toml b/test_programs/compile_success_empty/comptime_type/Nargo.toml new file mode 100644 index 00000000000..c5b9ca89240 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_type/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_type" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_type/src/main.nr b/test_programs/compile_success_empty/comptime_type/src/main.nr new file mode 100644 index 00000000000..6a2453ff0f2 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_type/src/main.nr @@ -0,0 +1,173 @@ +use std::meta::type_of; + +struct Foo { + x: T, +} + +trait SomeTrait {} +pub struct StructImplementsSomeTrait {} + +impl SomeTrait for StructImplementsSomeTrait {} + +pub struct StructDoesNotImplementSomeTrait {} + +// docs:start:serialize-setup +trait Serialize {} + +impl Serialize<1> for Field {} + +impl Serialize for [T; N] +where + T: Serialize, +{} + +impl Serialize for (T, U) +where + T: Serialize, + U: Serialize, +{} +// docs:end:serialize-setup + +fn main() { + comptime { + // Check type_of works correctly (relies on Eq for Type) + let a_field = 0; + let another_field = 1; + let an_i32: i32 = 0; + let field_type_1 = type_of(a_field); + let field_type_2 = type_of(another_field); + let i32_type = type_of(an_i32); + assert(field_type_1 == field_type_2); + assert(field_type_1 != i32_type); + + // Check Type::is_field + assert(field_type_1.is_field()); + assert(!i32_type.is_field()); + + // Check Type::as_integer + assert(field_type_1.as_integer().is_none()); + + let (signed, bits) = i32_type.as_integer().unwrap(); + assert(signed); + assert_eq(bits, 32); + + let a_u8: u8 = 0; + let u8_type = type_of(a_u8); + let (signed, bits) = u8_type.as_integer().unwrap(); + assert(!signed); + assert_eq(bits, 8); + + // Check Type::as_tuple + assert(u8_type.as_tuple().is_none()); + + let tuple = (an_i32, a_u8); + let tuple_type = type_of(tuple); + let tuple_types = tuple_type.as_tuple().unwrap(); + assert_eq(tuple_types.len(), 2); + assert_eq(tuple_types[0], i32_type); + assert_eq(tuple_types[1], u8_type); + + // Check Type::as_slice + assert(u8_type.as_slice().is_none()); + + let slice = &[1]; + let slice_type = type_of(slice); + let slice_type_element_type = slice_type.as_slice().unwrap(); + assert_eq(slice_type_element_type, field_type_1); + + // Check Type::as_array + assert(u8_type.as_array().is_none()); + + let array = [1, 2, 3]; + let array_type = type_of(array); + let (array_type_element_type, array_length) = array_type.as_array().unwrap(); + assert_eq(array_type_element_type, field_type_1); + + // Check Type::as_constant + assert(u8_type.as_constant().is_none()); + assert_eq(array_length.as_constant().unwrap(), 3); + + // Check Type::is_bool + assert(!u8_type.is_bool()); + + let yes = true; + let bool_type = type_of(yes); + assert(bool_type.is_bool()); + + // Check Type::as_struct + assert(u8_type.as_struct().is_none()); + + let foo = Foo { x: 0 }; + let foo_type = type_of(foo); + let (struct_definition, generics) = foo_type.as_struct().unwrap(); + let fields = struct_definition.fields(generics); + assert_eq(fields.len(), 1); + + assert_eq(generics.len(), 1); + assert_eq(generics[0], field_type_1); + + // Check Type::implements + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + let struct_implements_some_trait = quote { StructImplementsSomeTrait }.as_type(); + let struct_does_not_implement_some_trait = + quote { StructDoesNotImplementSomeTrait }.as_type(); + assert(struct_implements_some_trait.implements(some_trait_i32)); + assert(!struct_does_not_implement_some_trait.implements(some_trait_i32)); + + let some_trait_field = quote { SomeTrait }.as_trait_constraint(); + assert(!struct_implements_some_trait.implements(some_trait_field)); + assert(!struct_does_not_implement_some_trait.implements(some_trait_field)); + + let _trait_impl = struct_implements_some_trait.get_trait_impl(some_trait_i32).unwrap(); + + // Check Type::as_str + let str_type = quote { str<10> }.as_type(); + let constant = str_type.as_str().unwrap(); + assert_eq(constant.as_constant().unwrap(), 10); + + // Check std::meta::typ::fresh_type_variable + // docs:start:fresh-type-variable-example + let typevar1 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar1> }.as_trait_constraint(); + let field_type = quote { Field }.as_type(); + + // Search for a trait impl (binding typevar1 to 1 when the impl is found): + assert(field_type.implements(constraint)); + + // typevar1 should be bound to the "1" generic now: + assert_eq(typevar1.as_constant().unwrap(), 1); + + // If we want to do the same with a different type, we need to + // create a new type variable now that `typevar1` is bound + let typevar2 = std::meta::typ::fresh_type_variable(); + let constraint = quote { Serialize<$typevar2> }.as_trait_constraint(); + let array_type = quote { [(Field, Field); 5] }.as_type(); + assert(array_type.implements(constraint)); + + // Now typevar2 should be bound to the serialized pair size 2 times the array length 5 + assert_eq(typevar2.as_constant().unwrap(), 10); + // docs:end:fresh-type-variable-example + // Check Type::is_unit + let unit = quote { () }.as_type(); + assert(unit.is_unit()); + + // Check Type::as_mutable_reference + let typ = quote { &mut Field }.as_type(); + assert_eq(typ.as_mutable_reference().unwrap(), quote { Field }.as_type()); + } +} + +// docs:start:implements_example +pub fn function_with_where(_x: T) +where + T: SomeTrait, +{ + comptime { + let t = quote { T }.as_type(); + let some_trait_i32 = quote { SomeTrait }.as_trait_constraint(); + assert(t.implements(some_trait_i32)); + + assert(t.get_trait_impl(some_trait_i32).is_none()); + } +} +// docs:end:implements_example diff --git a/test_programs/compile_success_empty/comptime_typed_expr/Nargo.toml b/test_programs/compile_success_empty/comptime_typed_expr/Nargo.toml new file mode 100644 index 00000000000..151b8b8e9d0 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_typed_expr/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_typed_expr" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_typed_expr/src/main.nr b/test_programs/compile_success_empty/comptime_typed_expr/src/main.nr new file mode 100644 index 00000000000..361f6e8a1c8 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_typed_expr/src/main.nr @@ -0,0 +1,6 @@ +fn main() { + comptime { + let expr = quote { [1, 3] }.as_expr().unwrap().resolve(Option::none()); + assert_eq(expr.get_type().unwrap(), quote { [Field; 2] }.as_type()); + } +} diff --git a/test_programs/compile_success_empty/comptime_unresolved_type/Nargo.toml b/test_programs/compile_success_empty/comptime_unresolved_type/Nargo.toml new file mode 100644 index 00000000000..cc266b9b9c5 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_unresolved_type/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_unresolved_type" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/comptime_unresolved_type/src/main.nr b/test_programs/compile_success_empty/comptime_unresolved_type/src/main.nr new file mode 100644 index 00000000000..e3a5f7ad4ca --- /dev/null +++ b/test_programs/compile_success_empty/comptime_unresolved_type/src/main.nr @@ -0,0 +1,23 @@ +fn main() { + comptime { + // Check UnresolvedType::is_bool + let typ = quote { x as bool }.as_expr().unwrap().as_cast().unwrap().1; + assert(typ.is_bool()); + + // Check UnresolvedType::is_field + let typ = quote { x as Field }.as_expr().unwrap().as_cast().unwrap().1; + assert(typ.is_field()); + + // Check UnresolvedType::is_unit + let typ = quote { x as () }.as_expr().unwrap().as_cast().unwrap().1; + assert(typ.is_unit()); + + // Check UnresolvedType::as_mutable_reference + let typ = quote { x as &mut Field }.as_expr().unwrap().as_cast().unwrap().1; + assert(typ.as_mutable_reference().unwrap().is_field()); + + // Check UnresolvedType::as_slice + let typ = quote { x as [Field] }.as_expr().unwrap().as_cast().unwrap().1; + assert(typ.as_slice().unwrap().is_field()); + } +} diff --git a/test_programs/compile_success_empty/conditional_regression_579/Nargo.toml b/test_programs/compile_success_empty/conditional_regression_579/Nargo.toml new file mode 100644 index 00000000000..b440cb26e46 --- /dev/null +++ b/test_programs/compile_success_empty/conditional_regression_579/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_regression_579" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/conditional_regression_579/src/main.nr b/test_programs/compile_success_empty/conditional_regression_579/src/main.nr new file mode 100644 index 00000000000..758c6fefc28 --- /dev/null +++ b/test_programs/compile_success_empty/conditional_regression_579/src/main.nr @@ -0,0 +1,26 @@ +fn main() { + //Regression for Issue #579 + let result1_true = test(true); + assert(result1_true.array_param[0] == 1); + let result1_false = test(false); + assert(result1_false.array_param[0] == 0); +} + +struct MyStruct579 { + array_param: [u32; 2], +} + +impl MyStruct579 { + fn new(array_param: [u32; 2]) -> MyStruct579 { + MyStruct579 { array_param } + } +} + +fn test(flag: bool) -> MyStruct579 { + let mut my_struct = MyStruct579::new([0; 2]); + + if flag == true { + my_struct = MyStruct579::new([1; 2]); + } + my_struct +} diff --git a/test_programs/compile_success_empty/conditional_regression_to_bits/Nargo.toml b/test_programs/compile_success_empty/conditional_regression_to_bits/Nargo.toml new file mode 100644 index 00000000000..f2b13c4d547 --- /dev/null +++ b/test_programs/compile_success_empty/conditional_regression_to_bits/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_regression_to_bits" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/conditional_regression_to_bits/src/main.nr b/test_programs/compile_success_empty/conditional_regression_to_bits/src/main.nr new file mode 100644 index 00000000000..dd80d2c576f --- /dev/null +++ b/test_programs/compile_success_empty/conditional_regression_to_bits/src/main.nr @@ -0,0 +1,26 @@ +fn main() { + //Regression for to_le_bits() constant evaluation + // binary array representation of u8 1 + let arr: [u8; 2] = [1, 2]; + let as_bits_hardcode_1 = [1, 0]; + let mut c1 = 0; + for i in 0..2 { + let mut as_bits: [u1; 2] = (arr[i] as Field).to_le_bits(); + c1 = c1 + as_bits[0] as Field; + + if i == 0 { + assert(arr[i] == 1); // 1 + for k in 0..2 { + assert(as_bits_hardcode_1[k] == as_bits[k]); + } + } + if i == 1 { + assert(arr[i] == 2); //2 + for k in 0..2 { + assert(as_bits_hardcode_1[k] != as_bits[k]); + } + } + } + assert(c1 == 1); +} + diff --git a/test_programs/compile_success_empty/ctstring/Nargo.toml b/test_programs/compile_success_empty/ctstring/Nargo.toml new file mode 100644 index 00000000000..493fd8a6e4b --- /dev/null +++ b/test_programs/compile_success_empty/ctstring/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ctstring" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/ctstring/src/main.nr b/test_programs/compile_success_empty/ctstring/src/main.nr new file mode 100644 index 00000000000..818ae7f94e8 --- /dev/null +++ b/test_programs/compile_success_empty/ctstring/src/main.nr @@ -0,0 +1,19 @@ +use std::meta::ctstring::AsCtString; + +fn main() { + comptime { + let msg1 = "msg1"; + let msg2 = f" (msg2 contains {msg1}) "; + + let s1 = msg1.as_ctstring(); + let s2 = msg2.as_ctstring(); + + let s3 = &[s1, s2, s1].join("".as_ctstring()); + assert_eq(s3, "msg1 (msg2 contains msg1) msg1".as_ctstring()); + + let mut s4 = s1; + s4 = s4.append_fmtstr(msg2); + s4 = s4.append_str(msg1); + assert_eq(s3, s4); + } +} diff --git a/test_programs/compile_success_empty/derive_impl/Nargo.toml b/test_programs/compile_success_empty/derive_impl/Nargo.toml new file mode 100644 index 00000000000..26a6020a6b1 --- /dev/null +++ b/test_programs/compile_success_empty/derive_impl/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "derive_impl" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/derive_impl/src/main.nr b/test_programs/compile_success_empty/derive_impl/src/main.nr new file mode 100644 index 00000000000..fe7a7140280 --- /dev/null +++ b/test_programs/compile_success_empty/derive_impl/src/main.nr @@ -0,0 +1,53 @@ +comptime fn derive_default(typ: StructDefinition) -> Quoted { + let generics = typ.generics(); + assert_eq( + generics.len(), + 0, + "derive_default: Deriving Default on generic types is currently unimplemented", + ); + + let type_name = typ.as_type(); + let fields = typ.fields_as_written(); + + let fields = join(make_field_exprs(fields)); + + quote { + impl Default for $type_name { + fn default() -> Self { + Self { $fields } + } + } + } +} + +// Bar needs to be defined before Foo so that its impls are defined before +// Foo's are. +#[derive_default] +struct Bar {} + +#[derive_default] +struct Foo { + x: Field, + y: Bar, +} + +comptime fn make_field_exprs(fields: [(Quoted, Type)]) -> [Quoted] { + let mut result = &[]; + for my_field in fields { + let name = my_field.0; + result = result.push_back(quote { $name: Default::default(), }); + } + result +} + +comptime fn join(slice: [Quoted]) -> Quoted { + let mut result = quote {}; + for elem in slice { + result = quote { $result $elem }; + } + result +} + +fn main() { + let _foo: Foo = Default::default(); +} diff --git a/test_programs/compile_success_empty/double_generic_alias_in_path/Nargo.toml b/test_programs/compile_success_empty/double_generic_alias_in_path/Nargo.toml new file mode 100644 index 00000000000..aaebee8d6ef --- /dev/null +++ b/test_programs/compile_success_empty/double_generic_alias_in_path/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "double_generic_alias_in_path" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/double_generic_alias_in_path/src/main.nr b/test_programs/compile_success_empty/double_generic_alias_in_path/src/main.nr new file mode 100644 index 00000000000..09f2e5c4b43 --- /dev/null +++ b/test_programs/compile_success_empty/double_generic_alias_in_path/src/main.nr @@ -0,0 +1,14 @@ +struct Foo {} + +impl Foo { + fn new() -> Self { + Self {} + } +} + +type FooAlias1 = Foo; +type FooAlias2 = FooAlias1; + +fn main() { + let _ = FooAlias2::new(); +} diff --git a/test_programs/compile_success_empty/embedded_curve_add_simplification/Nargo.toml b/test_programs/compile_success_empty/embedded_curve_add_simplification/Nargo.toml new file mode 100644 index 00000000000..02586f5e926 --- /dev/null +++ b/test_programs/compile_success_empty/embedded_curve_add_simplification/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "embedded_curve_add_simplification" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/embedded_curve_add_simplification/src/main.nr b/test_programs/compile_success_empty/embedded_curve_add_simplification/src/main.nr new file mode 100644 index 00000000000..8984bd54979 --- /dev/null +++ b/test_programs/compile_success_empty/embedded_curve_add_simplification/src/main.nr @@ -0,0 +1,15 @@ +use std::embedded_curve_ops::EmbeddedCurvePoint; + +fn main() { + let zero = EmbeddedCurvePoint::point_at_infinity(); + let g1 = EmbeddedCurvePoint { + x: 1, + y: 17631683881184975370165255887551781615748388533673675138860, + is_infinite: false, + }; + + assert(g1 + zero == g1); + assert(g1 - g1 == zero); + assert(g1 - zero == g1); + assert(zero + zero == zero); +} diff --git a/test_programs/compile_success_empty/embedded_curve_msm_simplification/Nargo.toml b/test_programs/compile_success_empty/embedded_curve_msm_simplification/Nargo.toml new file mode 100644 index 00000000000..9c9bd8de04a --- /dev/null +++ b/test_programs/compile_success_empty/embedded_curve_msm_simplification/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "embedded_curve_msm_simplification" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/embedded_curve_msm_simplification/src/main.nr b/test_programs/compile_success_empty/embedded_curve_msm_simplification/src/main.nr new file mode 100644 index 00000000000..e5aaa0f4d15 --- /dev/null +++ b/test_programs/compile_success_empty/embedded_curve_msm_simplification/src/main.nr @@ -0,0 +1,12 @@ +fn main() { + let pub_x = 0x0000000000000000000000000000000000000000000000000000000000000001; + let pub_y = 0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c; + + 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: 1, 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.x == pub_x); + assert(res.y == pub_y); +} diff --git a/test_programs/compile_success_empty/empty/Nargo.toml b/test_programs/compile_success_empty/empty/Nargo.toml new file mode 100644 index 00000000000..168911f2b2b --- /dev/null +++ b/test_programs/compile_success_empty/empty/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "empty" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_success_empty/empty/src/main.nr b/test_programs/compile_success_empty/empty/src/main.nr new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/test_programs/compile_success_empty/empty/src/main.nr @@ -0,0 +1 @@ +fn main() {} diff --git a/test_programs/compile_success_empty/field_or_integer_static_trait_method/Nargo.toml b/test_programs/compile_success_empty/field_or_integer_static_trait_method/Nargo.toml new file mode 100644 index 00000000000..18d9fc90d9e --- /dev/null +++ b/test_programs/compile_success_empty/field_or_integer_static_trait_method/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "field_or_int_static_trait_method" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr b/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr new file mode 100644 index 00000000000..64eb564cda1 --- /dev/null +++ b/test_programs/compile_success_empty/field_or_integer_static_trait_method/src/main.nr @@ -0,0 +1,32 @@ +trait Read { + fn read(data: [Field; 1]) -> Self; +} + +impl Read for Field { + fn read(data: [Field; 1]) -> Self { + data[0] * 10 + } +} + +impl Read for u32 { + fn read(data: [Field; 1]) -> Self { + data[0] as u32 + } +} + +fn main() { + let data = [1]; + + let value: u32 = u32::read(data); + assert_eq(value, 1); + + let value: Field = Field::read(data); + assert_eq(value, 10); +} + +#[attr] +pub fn foo() {} + +comptime fn attr(_: FunctionDefinition) -> Quoted { + quote { pub fn hello() {} } +} diff --git a/test_programs/compile_success_empty/function_attribute/Nargo.toml b/test_programs/compile_success_empty/function_attribute/Nargo.toml new file mode 100644 index 00000000000..94b5c5da6a8 --- /dev/null +++ b/test_programs/compile_success_empty/function_attribute/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "function_attribute" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/function_attribute/src/main.nr b/test_programs/compile_success_empty/function_attribute/src/main.nr new file mode 100644 index 00000000000..1bc524d4cb5 --- /dev/null +++ b/test_programs/compile_success_empty/function_attribute/src/main.nr @@ -0,0 +1,18 @@ +#[function_attr] +pub fn foo() {} + +struct Foo {} + +comptime fn function_attr(_f: FunctionDefinition) -> Quoted { + quote { + impl Default for Foo { + fn default() -> Foo { + Foo {} + } + } + } +} + +fn main() { + let _ = Foo::default(); +} diff --git a/test_programs/compile_success_empty/generators/Nargo.toml b/test_programs/compile_success_empty/generators/Nargo.toml new file mode 100644 index 00000000000..58d8a993e16 --- /dev/null +++ b/test_programs/compile_success_empty/generators/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "generators" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/generators/src/main.nr b/test_programs/compile_success_empty/generators/src/main.nr new file mode 100644 index 00000000000..58aebc92b72 --- /dev/null +++ b/test_programs/compile_success_empty/generators/src/main.nr @@ -0,0 +1,56 @@ +// TODO? +// the syntax for these return types is very difficult to get right :/ +// for arguments this can be handled with a generic Env (or with Fn traits when we add them) +// but for return types neither fo these will help, you need to type out the exact type +fn make_counter() -> fn[(&mut Field,)]() -> Field { + let mut x = &mut 0; + + || { + *x = *x + 1; + *x + } +} + +fn fibonacci_generator() -> fn[(&mut Field, &mut Field)]() -> Field { + let mut x = &mut 1; + let mut y = &mut 2; + + || { + let old_x = *x; + let old_y = *y; + + *y = *x + *y; + *x = old_y; + + old_x + } +} +// we'll be able to un-hardcode the array length if we have the ::<> syntax proposed in https://github.com/noir-lang/noir/issues/2458 +fn get_some(generator: fn[Env]() -> Field) -> [Field; 5] { + [0, 0, 0, 0, 0].map(|_| generator()) +} + +fn test_fib() { + let fib = fibonacci_generator(); + + assert(fib() == 1); + assert(fib() == 2); + assert(fib() == 3); + assert(fib() == 5); + + assert(get_some(fib) == [8, 13, 21, 34, 55]); +} + +fn test_counter() { + let counter = make_counter(); + assert(counter() == 1); + assert(counter() == 2); + assert(counter() == 3); + + assert(get_some(counter) == [4, 5, 6, 7, 8]); +} + +fn main() { + test_fib(); + test_counter(); +} diff --git a/test_programs/compile_success_empty/higher_order_fn_selector/Nargo.toml b/test_programs/compile_success_empty/higher_order_fn_selector/Nargo.toml new file mode 100644 index 00000000000..968fc5300e6 --- /dev/null +++ b/test_programs/compile_success_empty/higher_order_fn_selector/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "higher_order_fn_selector" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_success_empty/higher_order_fn_selector/src/main.nr b/test_programs/compile_success_empty/higher_order_fn_selector/src/main.nr new file mode 100644 index 00000000000..99093c581b5 --- /dev/null +++ b/test_programs/compile_success_empty/higher_order_fn_selector/src/main.nr @@ -0,0 +1,30 @@ +fn g(x: &mut Field) -> () { + *x *= 2; +} + +fn h(x: &mut Field) -> () { + *x *= 3; +} + +fn selector(flag: &mut bool) -> fn(&mut Field) -> () { + let my_func = if *flag { g } else { h }; + // Flip the flag for the next function call + *flag = !(*flag); + my_func +} + +fn main() { + let mut flag: bool = true; + + let mut x: Field = 100; + let returned_func = selector(&mut flag); + returned_func(&mut x); + + assert(x == 200); + + let mut y: Field = 100; + let returned_func2 = selector(&mut flag); + returned_func2(&mut y); + + assert(y == 300); +} 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..8ce6ce3314d --- /dev/null +++ b/test_programs/compile_success_empty/impl_from_where_impl/src/main.nr @@ -0,0 +1,18 @@ +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/impl_where_clause/Nargo.toml b/test_programs/compile_success_empty/impl_where_clause/Nargo.toml new file mode 100644 index 00000000000..7d0d5f3513e --- /dev/null +++ b/test_programs/compile_success_empty/impl_where_clause/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "impl_where_clause" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/impl_where_clause/src/main.nr b/test_programs/compile_success_empty/impl_where_clause/src/main.nr new file mode 100644 index 00000000000..9cf0d26132c --- /dev/null +++ b/test_programs/compile_success_empty/impl_where_clause/src/main.nr @@ -0,0 +1,37 @@ +struct MyStruct { + a: u32, + b: T, +} + +struct InnerStruct { + a: Field, + b: Field, +} + +trait MyEq { + fn my_eq(self, other: Self) -> bool; +} + +impl MyEq for InnerStruct { + fn my_eq(self, other: InnerStruct) -> bool { + (self.a == other.a) & (self.b == other.b) + } +} + +impl MyStruct +where + T: MyEq, +{ + fn my_eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.my_eq(other.b) + } +} + +fn main() { + let inner = InnerStruct { a: 1, b: 2 }; + let my_struct = MyStruct { a: 5, b: inner }; + assert(my_struct.my_eq(my_struct)); + + let mut my_struct_new = MyStruct { a: 5, b: InnerStruct { a: 10, b: 15 } }; + assert(my_struct_new.my_eq(my_struct_new)); +} diff --git a/test_programs/compile_success_empty/inject_context_attribute/Nargo.toml b/test_programs/compile_success_empty/inject_context_attribute/Nargo.toml new file mode 100644 index 00000000000..10f9cb1f9e2 --- /dev/null +++ b/test_programs/compile_success_empty/inject_context_attribute/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "inject_context_attribute" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/inject_context_attribute/src/main.nr b/test_programs/compile_success_empty/inject_context_attribute/src/main.nr new file mode 100644 index 00000000000..963d4cea969 --- /dev/null +++ b/test_programs/compile_success_empty/inject_context_attribute/src/main.nr @@ -0,0 +1,62 @@ +struct Context { + value: Field, +} + +#[inject_context] +fn foo(x: Field) { + if true { + // 20 + 1 => 21 + bar(qux(x + 1) + zero()); + } else { + assert(false); + } +} + +#[inject_context] +fn bar(x: Field) { + let expected = _context.value; + assert_eq(x, expected); +} + +#[inject_context] +fn qux(x: Field) -> Field { + // 21 * 2 => 42 + x * 2 +} + +fn zero() -> Field { + 0 +} + +comptime fn inject_context(f: FunctionDefinition) { + // Add a `_context: Context` parameter to the function + let parameters = f.parameters(); + let parameters = parameters.push_front((quote { _context }, quote { Context }.as_type())); + f.set_parameters(parameters); + + // Create a new body where every function call has `_context` added to the list of arguments. + let body = f.body().modify(|expr| mapping_function(expr, f)); + f.set_body(body); +} + +comptime fn mapping_function(expr: Expr, f: FunctionDefinition) -> Option { + expr.as_function_call().and_then(|func_call: (Expr, [Expr])| { + let (name, arguments) = func_call; + name.resolve(Option::some(f)).as_function_definition().and_then( + |function_definition: FunctionDefinition| { + if function_definition.has_named_attribute("inject_context") { + let arguments = arguments.push_front(quote { _context }.as_expr().unwrap()); + let arguments = arguments.map(|arg: Expr| arg.quoted()).join(quote { , }); + Option::some(quote { $name($arguments) }.as_expr().unwrap()) + } else { + Option::none() + } + }, + ) + }) +} + +fn main() { + let context = Context { value: 42 }; + foo(context, 20); +} diff --git a/test_programs/compile_success_empty/inner_outer_cl/Nargo.toml b/test_programs/compile_success_empty/inner_outer_cl/Nargo.toml new file mode 100644 index 00000000000..073456fa7f6 --- /dev/null +++ b/test_programs/compile_success_empty/inner_outer_cl/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "inner_outer_cl" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/inner_outer_cl/src/main.nr b/test_programs/compile_success_empty/inner_outer_cl/src/main.nr new file mode 100644 index 00000000000..17cbabec48e --- /dev/null +++ b/test_programs/compile_success_empty/inner_outer_cl/src/main.nr @@ -0,0 +1,10 @@ +fn main() { + let z1 = 0; + let z2 = 1; + let cl_outer = |x| { + let cl_inner = |y| x + y + z2; + cl_inner(1) + z1 + }; + let result = cl_outer(1); + assert(result == 3); +} diff --git a/test_programs/compile_success_empty/instruction_deduplication/Nargo.toml b/test_programs/compile_success_empty/instruction_deduplication/Nargo.toml new file mode 100644 index 00000000000..4786a87ff65 --- /dev/null +++ b/test_programs/compile_success_empty/instruction_deduplication/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "instruction_deduplication" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_success_empty/instruction_deduplication/src/main.nr b/test_programs/compile_success_empty/instruction_deduplication/src/main.nr new file mode 100644 index 00000000000..43c0a382185 --- /dev/null +++ b/test_programs/compile_success_empty/instruction_deduplication/src/main.nr @@ -0,0 +1,5 @@ +fn main(x: Field) { + // This is a regression test for #2450. + // The compiler should recognize that the `(x as u32)` instructions are duplicates and so have the same output. + assert(x as u32 == x as u32); +} diff --git a/test_programs/compile_success_empty/intrinsic_die/Nargo.toml b/test_programs/compile_success_empty/intrinsic_die/Nargo.toml new file mode 100644 index 00000000000..539c536b944 --- /dev/null +++ b/test_programs/compile_success_empty/intrinsic_die/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "intrinsic_die" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_success_empty/intrinsic_die/src/main.nr b/test_programs/compile_success_empty/intrinsic_die/src/main.nr new file mode 100644 index 00000000000..17aaf02c283 --- /dev/null +++ b/test_programs/compile_success_empty/intrinsic_die/src/main.nr @@ -0,0 +1,8 @@ +// This test checks that we perform dead-instruction-elimination on intrinsic functions. +fn main(x: Field) { + 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/is_unconstrained/Nargo.toml b/test_programs/compile_success_empty/is_unconstrained/Nargo.toml new file mode 100644 index 00000000000..deef68c7f72 --- /dev/null +++ b/test_programs/compile_success_empty/is_unconstrained/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "is_unconstrained" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/is_unconstrained/src/main.nr b/test_programs/compile_success_empty/is_unconstrained/src/main.nr new file mode 100644 index 00000000000..856040b2274 --- /dev/null +++ b/test_programs/compile_success_empty/is_unconstrained/src/main.nr @@ -0,0 +1,17 @@ +use 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() { + /// Safety: testing context + unsafe { + unconstrained_intermediate(); + } + check(false); +} diff --git a/test_programs/compile_success_empty/let_stmt/Nargo.toml b/test_programs/compile_success_empty/let_stmt/Nargo.toml new file mode 100644 index 00000000000..def6e33b39a --- /dev/null +++ b/test_programs/compile_success_empty/let_stmt/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "let_stmt" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_success_empty/let_stmt/src/main.nr b/test_programs/compile_success_empty/let_stmt/src/main.nr new file mode 100644 index 00000000000..6c63ecd6e12 --- /dev/null +++ b/test_programs/compile_success_empty/let_stmt/src/main.nr @@ -0,0 +1,11 @@ +struct Foo { + a: u64, +} + +fn main() { + let _ = 42; + let _ = 42; + + let Foo { a: _ } = Foo { a: 42 }; + let _regression_2786 = [Foo { a: 1 }; 8]; +} diff --git a/test_programs/compile_success_empty/literal_not_simplification/Nargo.toml b/test_programs/compile_success_empty/literal_not_simplification/Nargo.toml new file mode 100644 index 00000000000..63d73ed3c0a --- /dev/null +++ b/test_programs/compile_success_empty/literal_not_simplification/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "literal_not_simplification" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/literal_not_simplification/src/main.nr b/test_programs/compile_success_empty/literal_not_simplification/src/main.nr new file mode 100644 index 00000000000..33198a326c9 --- /dev/null +++ b/test_programs/compile_success_empty/literal_not_simplification/src/main.nr @@ -0,0 +1,8 @@ +fn main() { + let four: u8 = 4; + let not_four: u8 = !four; + + let five: u8 = 5; + let not_five: u8 = !five; + assert(not_four != not_five); +} diff --git a/test_programs/compile_success_empty/macros/Nargo.toml b/test_programs/compile_success_empty/macros/Nargo.toml new file mode 100644 index 00000000000..e4408e2ee17 --- /dev/null +++ b/test_programs/compile_success_empty/macros/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "macros" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/macros/src/main.nr b/test_programs/compile_success_empty/macros/src/main.nr new file mode 100644 index 00000000000..587c2c4c077 --- /dev/null +++ b/test_programs/compile_success_empty/macros/src/main.nr @@ -0,0 +1,15 @@ +comptime fn my_macro(x: Field, y: Field) -> Quoted { + // Current version of macros in Noir are not hygienic + // so we can quote a and b here and expect them to resolve + // to the a and b in main at the callsite of my_macro. + quote { + $x + $y + a + b + } +} + +fn main() { + let a = 100; + let b = 200; + let result = my_macro!(1, 2); + assert_eq(result, 1 + 2 + a + b); +} diff --git a/test_programs/compile_success_empty/macros_in_comptime/Nargo.toml b/test_programs/compile_success_empty/macros_in_comptime/Nargo.toml new file mode 100644 index 00000000000..831fa270863 --- /dev/null +++ b/test_programs/compile_success_empty/macros_in_comptime/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "macros_in_comptime" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/macros_in_comptime/src/main.nr b/test_programs/compile_success_empty/macros_in_comptime/src/main.nr new file mode 100644 index 00000000000..0572192225c --- /dev/null +++ b/test_programs/compile_success_empty/macros_in_comptime/src/main.nr @@ -0,0 +1,51 @@ +use std::field::modulus_num_bits; +use std::meta::unquote; + +// Numeric generics default to u32 +global three_field: Field = 3; + +fn main() { + comptime { + foo::(5); + submodule::bar(); + } +} + +// Call a different function from the interpreter, then have the +// elaborator switch to the middle of foo from its previous scope in main +comptime fn foo(x: Field) { + assert(modulus_num_bits() != 0); + + let cond = quote { modulus_num_bits() != 0 }; + assert(unquote!(cond)); + + // Use a comptime parameter in scope + assert_eq(5, x); + assert_eq(5, unquote!(quote { x })); + + // Use a generic in scope + assert_eq(3, N); + assert_eq(3, unquote!(quote { N })); + + // Use `break` which only unconstrained functions can do. + // This ensures the elaborator knows we're switching from `main` to `foo` + for _ in 0..0 { + break; + } + + let loop = quote { for _ in 0..0 { break; } }; + unquote!(loop); +} + +mod submodule { + use std::field::modulus_be_bytes; + use std::meta::unquote; + + pub comptime fn bar() { + // Use a function only in scope in this module + assert(modulus_be_bytes().len() != 0); + + let cond = quote { modulus_be_bytes().len() != 0 }; + assert(unquote!(cond)); + } +} diff --git a/test_programs/compile_success_empty/method_call_regression/Nargo.toml b/test_programs/compile_success_empty/method_call_regression/Nargo.toml new file mode 100644 index 00000000000..09f95590aad --- /dev/null +++ b/test_programs/compile_success_empty/method_call_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "method_call_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.19.4" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/method_call_regression/src/main.nr b/test_programs/compile_success_empty/method_call_regression/src/main.nr new file mode 100644 index 00000000000..f5b28978ef7 --- /dev/null +++ b/test_programs/compile_success_empty/method_call_regression/src/main.nr @@ -0,0 +1,30 @@ +fn main() { + // s: Struct + let s = Struct { a: 0, b: () }; + // Regression for #3089 + s.foo(); +} + +struct Struct { + a: A, + b: B, +} + +// Before the fix, this candidate is searched first, binding ? to `u8` permanently. +impl Struct { + fn foo(self) { + let _ = self; + } +} + +// Then this candidate would be searched next but would not be a valid +// candidate since `Struct` != `Struct`. +// +// With the fix, the type of `s` correctly no longer changes until a +// method is actually selected. So this candidate is now valid since +// `Struct` unifies with `Struct` with `? = u32`. +impl Struct { + fn foo(self) { + let _ = self; + } +} diff --git a/test_programs/compile_success_empty/mod_nr_entrypoint/Nargo.toml b/test_programs/compile_success_empty/mod_nr_entrypoint/Nargo.toml new file mode 100644 index 00000000000..b90b7326186 --- /dev/null +++ b/test_programs/compile_success_empty/mod_nr_entrypoint/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "mod_nr_entrypoint" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/mod_nr_entrypoint/src/baz.nr b/test_programs/compile_success_empty/mod_nr_entrypoint/src/baz.nr new file mode 100644 index 00000000000..0bcfe8b02ad --- /dev/null +++ b/test_programs/compile_success_empty/mod_nr_entrypoint/src/baz.nr @@ -0,0 +1,3 @@ +pub fn in_baz_mod() -> bool { + true +} diff --git a/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/bar.nr b/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/bar.nr new file mode 100644 index 00000000000..f2efe64906d --- /dev/null +++ b/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/bar.nr @@ -0,0 +1,3 @@ +pub fn in_bar_mod() -> Field { + 2 +} diff --git a/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/mod.nr b/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/mod.nr new file mode 100644 index 00000000000..216294fbf08 --- /dev/null +++ b/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/mod.nr @@ -0,0 +1,5 @@ +pub mod bar; + +pub fn in_foo_mod() -> Field { + 1 +} diff --git a/test_programs/compile_success_empty/mod_nr_entrypoint/src/main.nr b/test_programs/compile_success_empty/mod_nr_entrypoint/src/main.nr new file mode 100644 index 00000000000..972a64bfeb9 --- /dev/null +++ b/test_programs/compile_success_empty/mod_nr_entrypoint/src/main.nr @@ -0,0 +1,11 @@ +use crate::baz::in_baz_mod; +use crate::foo::bar::in_bar_mod; +use crate::foo::in_foo_mod; + +mod foo; +mod baz; + +fn main() { + assert(in_foo_mod() != in_bar_mod()); + assert(in_baz_mod()); +} diff --git a/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml b/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml new file mode 100644 index 00000000000..2125d475530 --- /dev/null +++ b/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "no_duplicate_methods" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr b/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr new file mode 100644 index 00000000000..7e25a61d2ff --- /dev/null +++ b/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr @@ -0,0 +1,32 @@ +// Test that declaring several methods & trait methods with the same name +// does not trigger a duplicate method error +trait ToField { + fn to_field(self) -> Field; +} +trait ToField2 { + fn to_field(self) -> Field; +} + +pub struct Foo { + x: Field, +} + +impl ToField for Foo { + fn to_field(self) -> Field { + self.x + } +} + +impl ToField2 for Foo { + fn to_field(self) -> Field { + self.x + } +} + +impl Foo { + fn to_field(self) -> Field { + self.x + } +} + +fn main() {} diff --git a/test_programs/compile_success_empty/numeric_generics/Nargo.toml b/test_programs/compile_success_empty/numeric_generics/Nargo.toml new file mode 100644 index 00000000000..835c945c3b8 --- /dev/null +++ b/test_programs/compile_success_empty/numeric_generics/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "numeric_generics" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/numeric_generics/src/main.nr b/test_programs/compile_success_empty/numeric_generics/src/main.nr new file mode 100644 index 00000000000..1bdde60bcd5 --- /dev/null +++ b/test_programs/compile_success_empty/numeric_generics/src/main.nr @@ -0,0 +1,38 @@ +fn main() { + let a = id([1, 2]); + let b = id([1, 2, 3]); + + let itWorks1 = MyStruct { data: a }; + assert(itWorks1.data[1] == 2); + let itWorks2 = MyStruct { data: b }; + assert(itWorks2.data[1] == 2); + + let c = [1, 2]; + let itAlsoWorks = MyStruct { data: c }; + assert(itAlsoWorks.data[1] == 2); + + assert(foo(itWorks2).data[0] == itWorks2.data[0] + 1); +} + +fn id(x: [Field; I]) -> [Field; I] { + x +} + +struct MyStruct { + data: [Field; S], +} + +impl MyStruct { + fn insert(mut self: Self, index: Field, elem: Field) -> Self { + // Regression test for numeric generics on impls + assert(index as u64 < S as u64); + + self.data[index] = elem; + self + } +} + +fn foo(mut s: MyStruct<2 + 1>) -> MyStruct<10 / 2 - 2> { + s.data[0] = s.data[0] + 1; + s +} diff --git a/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml b/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml new file mode 100644 index 00000000000..980e5db588a --- /dev/null +++ b/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "numeric_generics_explicit" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr b/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr new file mode 100644 index 00000000000..978a7fdf66b --- /dev/null +++ b/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr @@ -0,0 +1,114 @@ +// Regression that a global of the same name does not trigger a duplicate definition error +global N: u32 = 1000; + +fn main() { + let a = id([1, 2]); + let b = id([1, 2, 3]); + + let itWorks1 = MyStruct { data: a }; + assert(itWorks1.data[1] == 2); + let itWorks2 = MyStruct { data: b }; + assert(itWorks2.data[1] == 2); + + let c = [1, 2]; + let itAlsoWorks = MyStruct { data: c }; + assert(itAlsoWorks.data[1] == 2); + + assert(foo(itWorks2).data[0] == itWorks2.data[0] + 1); + + double_numeric_generics_test(); + + let my_type = PublicStorage::read::(); + assert(my_type.a == 1); + assert(my_type.b == 2); + assert(my_type.c == 3); + + let foo = baz::<10>(); + assert(foo.data == [1; 10]); +} + +// Used in the signature of a function +fn id(x: [Field; I]) -> [Field; I] { + x +} + +// Used as a field of a struct +struct MyStruct { + data: [Field; S], +} + +// Used in an impl +impl MyStruct { + fn insert(mut self: Self, index: Field, elem: Field) -> Self { + // Regression test for numeric generics on impls + assert(index as u32 < S); + + self.data[index] = elem; + self + } +} + +fn foo(mut s: MyStruct<2 + 1>) -> MyStruct<10 / 2 - 2> { + s.data[0] = s.data[0] + 1; + s +} + +fn baz() -> MyStruct { + MyStruct { data: [1; N] } +} + +fn double() -> u32 { + // Used as an expression + N * 2 +} + +fn double_numeric_generics_test() { + // Example usage of a numeric generic arguments. + assert(double::<9>() == 18); + assert(double::<123>() == 246); + assert(double::<7 + 8>() == 30); +} + +struct MyType { + a: Field, + b: Field, + c: Field, +} + +impl Deserialize for MyType { + fn deserialize(fields: [Field; N]) -> Self { + MyType { a: fields[0], b: fields[1], c: fields[2] } + } +} + +trait Deserialize { + fn deserialize(fields: [Field; N]) -> Self; +} + +pub struct PublicStorage {} + +impl PublicStorage { + fn read() -> T + where + T: Deserialize, + { + // Used as a type within a function body + let mut fields: [Field; N] = [0; N]; + // Used a loop bound + for i in 0..N { + fields[i] = i as Field + 1; + } + T::deserialize(fields) + } +} + +// Check that we can thread numeric generics into nested structs +// and also that we can handle nested structs with numeric generics +// which are declared after the parent struct +pub struct NestedNumeric { + a: Field, + b: InnerNumeric, +} +pub struct InnerNumeric { + inner: [u32; N], +} diff --git a/test_programs/compile_success_empty/option/Nargo.toml b/test_programs/compile_success_empty/option/Nargo.toml new file mode 100644 index 00000000000..d9bec3c3096 --- /dev/null +++ b/test_programs/compile_success_empty/option/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "option" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_success_empty/option/src/main.nr b/test_programs/compile_success_empty/option/src/main.nr new file mode 100644 index 00000000000..d135b2d88b8 --- /dev/null +++ b/test_programs/compile_success_empty/option/src/main.nr @@ -0,0 +1,63 @@ +fn main() { + let ten = 10; // giving this a name, to ensure that the Option functions work with closures + let none: Option = Option::none(); + let some = Option::some(3); + + assert(none.is_none()); + assert(some.is_some()); + + assert(some.unwrap() == 3); + + assert(none.unwrap_or(2) == 2); + assert(some.unwrap_or(2) == 3); + + assert(none.unwrap_or_else(|| 5) == 5); + assert(some.unwrap_or_else(|| 5) == 3); + assert(none.unwrap_or_else(|| ten + 5) == 15); + assert(some.unwrap_or_else(|| ten + 5) == 3); + + assert(none.map(|x| x * 2).is_none()); + assert(some.map(|x| x * 2).unwrap() == 6); + assert(some.map(|x| x * ten).unwrap() == 30); + + assert(some.expect(f"Should have a value") == 3); + + assert(none.map_or(0, |x| x * 2) == 0); + assert(some.map_or(0, |x| x * 2) == 6); + assert(none.map_or(0, |x| x * ten) == 0); + assert(some.map_or(0, |x| x * ten) == 30); + + assert(none.map_or_else(|| 0, |x| x * 2) == 0); + assert(some.map_or_else(|| 0, |x| x * 2) == 6); + assert(none.map_or_else(|| 0, |x| x * ten) == 0); + assert(some.map_or_else(|| ten, |x| x * 2) == 6); + + assert(none.and(none).is_none()); + assert(none.and(some).is_none()); + assert(some.and(none).is_none()); + assert(some.and(some).is_some()); + + let add1_u64 = |value: Field| Option::some(value as u64 + 1); + + assert(none.and_then(|_value| none).is_none()); + assert(none.and_then(add1_u64).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); + + assert(none.or(none).is_none()); + assert(none.or(some).is_some()); + assert(some.or(none).is_some()); + assert(some.or(some).is_some()); + + assert(none.or_else(|| Option::none()).is_none()); + assert(none.or_else(|| Option::some(5)).is_some()); + assert(some.or_else(|| Option::none()).is_some()); + assert(some.or_else(|| Option::some(5)).is_some()); + assert(some.or_else(|| Option::some(ten)).is_some()); + + assert(none.xor(none).is_none()); + assert(none.xor(some).is_some()); + assert(some.xor(none).is_some()); + assert(some.xor(some).is_none()); +} diff --git a/test_programs/compile_success_empty/overlapping_dep_and_mod/Nargo.toml b/test_programs/compile_success_empty/overlapping_dep_and_mod/Nargo.toml new file mode 100644 index 00000000000..b2c3e5f94be --- /dev/null +++ b/test_programs/compile_success_empty/overlapping_dep_and_mod/Nargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "bin", + "foo", +] +default-member = "bin" diff --git a/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/Nargo.toml b/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/Nargo.toml new file mode 100644 index 00000000000..57e704462db --- /dev/null +++ b/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "overlapping_dep_and_mod" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] +foo = { path = "../foo" } diff --git a/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/src/main.nr b/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/src/main.nr new file mode 100644 index 00000000000..1d9c917d91a --- /dev/null +++ b/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/src/main.nr @@ -0,0 +1,9 @@ +fn main() { + let _ = foo::bar() + dep::foo::baz(); +} + +mod foo { + pub(crate) fn bar() -> Field { + 5 + } +} diff --git a/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/Nargo.toml b/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/Nargo.toml new file mode 100644 index 00000000000..857d4e722a8 --- /dev/null +++ b/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "foo" +type = "lib" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/src/lib.nr b/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/src/lib.nr new file mode 100644 index 00000000000..cb8392ed275 --- /dev/null +++ b/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/src/lib.nr @@ -0,0 +1,5 @@ +// foo/lib.nr + +pub fn baz() -> Field { + 6 +} diff --git a/test_programs/compile_success_empty/parenthesized_expression_in_array_length/Nargo.toml b/test_programs/compile_success_empty/parenthesized_expression_in_array_length/Nargo.toml new file mode 100644 index 00000000000..e56e9643f40 --- /dev/null +++ b/test_programs/compile_success_empty/parenthesized_expression_in_array_length/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "parenthesized_expression_in_array_length" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/parenthesized_expression_in_array_length/src/main.nr b/test_programs/compile_success_empty/parenthesized_expression_in_array_length/src/main.nr new file mode 100644 index 00000000000..d4479ec933b --- /dev/null +++ b/test_programs/compile_success_empty/parenthesized_expression_in_array_length/src/main.nr @@ -0,0 +1,6 @@ +global N: u32 = 100; +global BLOCK_SIZE: u32 = 10; + +fn main() { + let _: [Field; 110] = [0; ((N + BLOCK_SIZE) * BLOCK_SIZE) / BLOCK_SIZE]; +} diff --git a/test_programs/compile_success_empty/poseidon2_simplification/Nargo.toml b/test_programs/compile_success_empty/poseidon2_simplification/Nargo.toml new file mode 100644 index 00000000000..fbf2c11b220 --- /dev/null +++ b/test_programs/compile_success_empty/poseidon2_simplification/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "poseidon2_simplification" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/poseidon2_simplification/src/main.nr b/test_programs/compile_success_empty/poseidon2_simplification/src/main.nr new file mode 100644 index 00000000000..423dfcc4d3b --- /dev/null +++ b/test_programs/compile_success_empty/poseidon2_simplification/src/main.nr @@ -0,0 +1,7 @@ +use std::hash::poseidon2; + +fn main() { + let digest = poseidon2::Poseidon2::hash([0], 1); + let expected_digest = 0x2710144414c3a5f2354f4c08d52ed655b9fe253b4bf12cb9ad3de693d9b1db11; + assert_eq(digest, expected_digest); +} diff --git a/test_programs/compile_success_empty/quoted_as_type/Nargo.toml b/test_programs/compile_success_empty/quoted_as_type/Nargo.toml new file mode 100644 index 00000000000..7d669ead363 --- /dev/null +++ b/test_programs/compile_success_empty/quoted_as_type/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "quoted_as_type" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/quoted_as_type/src/main.nr b/test_programs/compile_success_empty/quoted_as_type/src/main.nr new file mode 100644 index 00000000000..e06294592ca --- /dev/null +++ b/test_programs/compile_success_empty/quoted_as_type/src/main.nr @@ -0,0 +1,21 @@ +fn main() { + macro!().do_nothing(); +} + +comptime fn macro() -> Quoted { + let typ = quote { Foo }.as_type(); + quote { let foo: $typ = Foo {}; foo } +} + +struct Foo {} + +// Ensure we call the Foo impl +impl Foo { + fn do_nothing(_self: Self) { + assert(false); + } +} + +impl Foo { + fn do_nothing(_self: Self) {} +} diff --git a/test_programs/compile_success_empty/raw_string/Nargo.toml b/test_programs/compile_success_empty/raw_string/Nargo.toml new file mode 100644 index 00000000000..81147e65f34 --- /dev/null +++ b/test_programs/compile_success_empty/raw_string/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "raw_string" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/raw_string/src/main.nr b/test_programs/compile_success_empty/raw_string/src/main.nr new file mode 100644 index 00000000000..6bed1cfecc9 --- /dev/null +++ b/test_programs/compile_success_empty/raw_string/src/main.nr @@ -0,0 +1,13 @@ +global D: str<13> = r#####"Hello "world""#####; + +fn main() { + let a = "Hello \"world\""; + let b = r#"Hello "world""#; + let c = r##"Hello "world""##; + assert(a == b); + assert(b == c); + assert(c == D); + let x = r#"Hello World"#; + let y = r"Hello World"; + assert(x == y); +} diff --git a/test_programs/compile_success_empty/reexports/Nargo.toml b/test_programs/compile_success_empty/reexports/Nargo.toml new file mode 100644 index 00000000000..4a87f28fd89 --- /dev/null +++ b/test_programs/compile_success_empty/reexports/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "reexports" +type = "bin" +authors = [""] + +[dependencies] +reexporting_lib = { path = "../../test_libraries/reexporting_lib" } diff --git a/test_programs/compile_success_empty/reexports/src/main.nr b/test_programs/compile_success_empty/reexports/src/main.nr new file mode 100644 index 00000000000..6b568bea682 --- /dev/null +++ b/test_programs/compile_success_empty/reexports/src/main.nr @@ -0,0 +1,6 @@ +use reexporting_lib::{FooStruct, lib, MyStruct}; + +fn main() { + let x: FooStruct = MyStruct { inner: 0 }; + assert(lib::is_struct_zero(x)); +} diff --git a/test_programs/compile_success_empty/references_aliasing/Nargo.toml b/test_programs/compile_success_empty/references_aliasing/Nargo.toml new file mode 100644 index 00000000000..0310e55ed7e --- /dev/null +++ b/test_programs/compile_success_empty/references_aliasing/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "references_aliasing" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/references_aliasing/src/main.nr b/test_programs/compile_success_empty/references_aliasing/src/main.nr new file mode 100644 index 00000000000..b2b625477e7 --- /dev/null +++ b/test_programs/compile_success_empty/references_aliasing/src/main.nr @@ -0,0 +1,59 @@ +fn main() { + let mut x = 100; + let mut xref = &mut x; + increment(xref); + assert(*xref == 101); + + regression_2445(); + single_alias_inside_loop(); + assert(5 == struct_field_refs_across_blocks(MyStruct { a: 5, b: 10 })[0]); +} + +fn increment(mut r: &mut Field) { + *r = *r + 1; +} +// If aliasing within arrays and constant folding within the mem2reg pass aren't +// handled, we'll fail to optimize out all the references in this function. +fn regression_2445() { + let mut var = 0; + let ref = &mut &mut var; + + let mut array = [ref, ref]; + + **array[0] = 1; + **array[1] = 2; + + assert(var == 2); + assert(**ref == 2); + assert(**array[0] == 2); + assert(**array[1] == 2); +} + +fn single_alias_inside_loop() { + let mut var = 0; + let ref = &mut &mut var; + + for _ in 0..1 { + **ref = 2; + } + + assert(var == 2); + assert(**ref == 2); +} + +struct MyStruct { + a: Field, + b: u32, +} + +fn struct_field_refs_across_blocks(mut my_struct: MyStruct) -> [Field; 1] { + [compute_dummy_hash(my_struct.a, my_struct.b, 20)] +} + +fn compute_dummy_hash(input: Field, rhs: u32, in_len: u32) -> Field { + let mut res = 0; + if rhs < in_len { + res += input; + } + res +} diff --git a/test_programs/compile_success_empty/regression_2099/Nargo.toml b/test_programs/compile_success_empty/regression_2099/Nargo.toml new file mode 100644 index 00000000000..69fd4caabed --- /dev/null +++ b/test_programs/compile_success_empty/regression_2099/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_2099" +type = "bin" +authors = [""] + +[dependencies] +ec = { tag = "v0.1.2", git = "https://github.com/noir-lang/ec" } diff --git a/test_programs/compile_success_empty/regression_2099/src/main.nr b/test_programs/compile_success_empty/regression_2099/src/main.nr new file mode 100644 index 00000000000..3a8b9092792 --- /dev/null +++ b/test_programs/compile_success_empty/regression_2099/src/main.nr @@ -0,0 +1,34 @@ +use ec::tecurve::affine::Curve as AffineCurve; +use ec::tecurve::affine::Point as Gaffine; + +fn main() { + // Define Baby Jubjub (ERC-2494) parameters in affine representation + let bjj_affine = AffineCurve::new( + 168700, + 168696, + Gaffine::new( + 995203441582195749578291179787384436505546430278305826713579947235728471134, + 5472060717959818805561601436314318772137091100104008585924551046643952123905, + ), + ); + // Test addition + let p1_affine = Gaffine::new( + 17777552123799933955779906779655732241715742912184938656739573121738514868268, + 2626589144620713026669568689430873010625803728049924121243784502389097019475, + ); + let p2_affine = Gaffine::new( + 16540640123574156134436876038791482806971768689494387082833631921987005038935, + 20819045374670962167435360035096875258406992893633759881276124905556507972311, + ); + let _p3_affine = bjj_affine.add(p1_affine, p2_affine); + // Test SWCurve equivalents of the above + // First the affine representation + let bjj_swcurve_affine = bjj_affine.into_swcurve(); + + let p1_swcurve_affine = bjj_affine.map_into_swcurve(p1_affine); + let p2_swcurve_affine = bjj_affine.map_into_swcurve(p2_affine); + + let _p3_swcurve_affine_from_add = bjj_swcurve_affine.add(p1_swcurve_affine, p2_swcurve_affine); + // Check that these points are on the curve + assert(bjj_swcurve_affine.contains(p1_swcurve_affine)); +} diff --git a/test_programs/compile_success_empty/regression_3635/Nargo.toml b/test_programs/compile_success_empty/regression_3635/Nargo.toml new file mode 100644 index 00000000000..4f34121439e --- /dev/null +++ b/test_programs/compile_success_empty/regression_3635/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_3635" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_3635/src/main.nr b/test_programs/compile_success_empty/regression_3635/src/main.nr new file mode 100644 index 00000000000..edc6d8690e8 --- /dev/null +++ b/test_programs/compile_success_empty/regression_3635/src/main.nr @@ -0,0 +1,6 @@ +fn main() { + let x: u8 = 0x61; + let y: u8 = "a".as_bytes()[0]; + assert_eq(x, y); + assert_eq(x >> 1, y >> 1); +} diff --git a/test_programs/compile_success_empty/regression_3964/Nargo.toml b/test_programs/compile_success_empty/regression_3964/Nargo.toml new file mode 100644 index 00000000000..a3fd040bcc2 --- /dev/null +++ b/test_programs/compile_success_empty/regression_3964/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_3964" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_3964/src/main.nr b/test_programs/compile_success_empty/regression_3964/src/main.nr new file mode 100644 index 00000000000..0600a4281a0 --- /dev/null +++ b/test_programs/compile_success_empty/regression_3964/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + let one: u8 = 1; + let p = ((one, 2), (3, 4)); + assert(p == p); +} 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..30e4a942bdf --- /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; +} + +pub global STRUCT_A_LEN: u32 = 3; +pub global STRUCT_B_LEN: u32 = 5; + +pub struct StructA; +pub struct StructB; + +impl LibTrait for StructA { + fn broadcast() { + let _ = Self::get_constant(); + } + + fn get_constant() -> Field { + 1 + } +} +impl LibTrait for StructB { + fn broadcast() { + let _ = 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..f33effb6bdb --- /dev/null +++ b/test_programs/compile_success_empty/regression_4635/src/main.nr @@ -0,0 +1,61 @@ +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: u32 = 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 +where + T: FromField, +{ + fn deserialize(fields: [Field; 1]) -> Self { + 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..6ffb6e4e237 --- /dev/null +++ b/test_programs/compile_success_empty/regression_5065/src/main.nr @@ -0,0 +1,48 @@ +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/regression_5428/Nargo.toml b/test_programs/compile_success_empty/regression_5428/Nargo.toml new file mode 100644 index 00000000000..7507b934d66 --- /dev/null +++ b/test_programs/compile_success_empty/regression_5428/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_5428" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_5428/src/main.nr b/test_programs/compile_success_empty/regression_5428/src/main.nr new file mode 100644 index 00000000000..e9e6c8a5dc8 --- /dev/null +++ b/test_programs/compile_success_empty/regression_5428/src/main.nr @@ -0,0 +1,11 @@ +use std::append::Append; + +fn main() { + assert_true!(); +} + +comptime fn assert_true() -> Quoted { + let first = quote { assert( }; + let second = quote { true); }; + first.append(second) +} diff --git a/test_programs/compile_success_empty/regression_5462/Nargo.toml b/test_programs/compile_success_empty/regression_5462/Nargo.toml new file mode 100644 index 00000000000..97015f78963 --- /dev/null +++ b/test_programs/compile_success_empty/regression_5462/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5462" +type = "bin" +authors = [""] +compiler_version = ">=0.35.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_5462/src/main.nr b/test_programs/compile_success_empty/regression_5462/src/main.nr new file mode 100644 index 00000000000..092f7ab96a5 --- /dev/null +++ b/test_programs/compile_success_empty/regression_5462/src/main.nr @@ -0,0 +1,11 @@ +fn main() { + let empty_slice: [u8] = &[]; + + if empty_slice != &[] { + let _ = empty_slice.pop_front(); + } + + if empty_slice.len() != 0 { + let _ = empty_slice.pop_front(); + } +} diff --git a/test_programs/compile_success_empty/regression_5671/Nargo.toml b/test_programs/compile_success_empty/regression_5671/Nargo.toml new file mode 100644 index 00000000000..4ddf3413e5e --- /dev/null +++ b/test_programs/compile_success_empty/regression_5671/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5671" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_5671/src/main.nr b/test_programs/compile_success_empty/regression_5671/src/main.nr new file mode 100644 index 00000000000..2bac98ef7c4 --- /dev/null +++ b/test_programs/compile_success_empty/regression_5671/src/main.nr @@ -0,0 +1,20 @@ +#[foo] +struct MyOtherStruct { + field1: A, + field2: B, +} + +comptime fn foo(_s: StructDefinition) -> Quoted { + quote { + impl Eq for MyOtherStruct where A: Eq, B: Eq { + fn eq(self, other: Self) -> bool { + (self.field1 == other.field1) & (self.field2 == other.field2) + } + } + } +} + +fn main() { + let x = MyOtherStruct { field1: 1, field2: 2 }; + assert_eq(x, x); +} diff --git a/test_programs/compile_success_empty/regression_5823/Nargo.toml b/test_programs/compile_success_empty/regression_5823/Nargo.toml new file mode 100644 index 00000000000..a2de5c954b9 --- /dev/null +++ b/test_programs/compile_success_empty/regression_5823/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5823" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/regression_5823/src/main.nr b/test_programs/compile_success_empty/regression_5823/src/main.nr new file mode 100644 index 00000000000..f615564fae2 --- /dev/null +++ b/test_programs/compile_success_empty/regression_5823/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + let x = 1 as u64; + let y = 2 as u8; + assert_eq(x << y, 4); +} diff --git a/test_programs/compile_success_empty/regression_6077/Nargo.toml b/test_programs/compile_success_empty/regression_6077/Nargo.toml new file mode 100644 index 00000000000..0c1118245f4 --- /dev/null +++ b/test_programs/compile_success_empty/regression_6077/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_6077" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_6077/Prover.toml b/test_programs/compile_success_empty/regression_6077/Prover.toml new file mode 100644 index 00000000000..ba3522cab01 --- /dev/null +++ b/test_programs/compile_success_empty/regression_6077/Prover.toml @@ -0,0 +1 @@ +a = 0 diff --git a/test_programs/compile_success_empty/regression_6077/src/main.nr b/test_programs/compile_success_empty/regression_6077/src/main.nr new file mode 100644 index 00000000000..971d487316f --- /dev/null +++ b/test_programs/compile_success_empty/regression_6077/src/main.nr @@ -0,0 +1,30 @@ +pub struct WeirdStruct { + a: T, + b: U, +} + +#[mangle_fn] +pub fn my_fn() -> [u8; 3] { + [0; 3] +} + +comptime fn mangle_fn(f: FunctionDefinition) { + let return_type = f.return_type(); + + // This relies on how types are displayed + let generics = f"Field,{return_type}".quoted_contents(); + let new_return_type = quote { WeirdStruct<$generics>}.as_type(); + + let new_body = quote { + { + WeirdStruct { a: 1, b: [0;3] } + } + } + .as_expr() + .unwrap(); + + f.set_return_type(new_return_type); + f.set_body(new_body); +} + +fn main() {} diff --git a/test_programs/compile_success_empty/regression_7038/Nargo.toml b/test_programs/compile_success_empty/regression_7038/Nargo.toml new file mode 100644 index 00000000000..3c874d4b6e8 --- /dev/null +++ b/test_programs/compile_success_empty/regression_7038/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_7038" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_7038/src/main.nr b/test_programs/compile_success_empty/regression_7038/src/main.nr new file mode 100644 index 00000000000..793a3f60807 --- /dev/null +++ b/test_programs/compile_success_empty/regression_7038/src/main.nr @@ -0,0 +1,40 @@ +trait BigNumTrait {} + +pub struct MyBigNum; + +impl crate::BigNumTrait for MyBigNum {} + +trait CurveParamsTrait +where + BigNum: BigNumTrait, +{ + fn one(); +} + +pub struct BN254Params; +impl CurveParamsTrait for BN254Params { + + fn one() {} +} + +trait BigCurveTrait { + fn two(); +} + +pub struct BigCurve {} + +type BN254 = BigCurve; + +impl BigCurveTrait for BigCurve +where + BigNum: BigNumTrait, + CurveParams: CurveParamsTrait, +{ + fn two() { + let _ = CurveParams::one(); + } +} + +fn main() { + let _ = BN254::two(); +} diff --git a/test_programs/compile_success_empty/regression_7038_2/Nargo.toml b/test_programs/compile_success_empty/regression_7038_2/Nargo.toml new file mode 100644 index 00000000000..f4f23683eb8 --- /dev/null +++ b/test_programs/compile_success_empty/regression_7038_2/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_7038_2" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_7038_2/src/main.nr b/test_programs/compile_success_empty/regression_7038_2/src/main.nr new file mode 100644 index 00000000000..6a116bb0722 --- /dev/null +++ b/test_programs/compile_success_empty/regression_7038_2/src/main.nr @@ -0,0 +1,39 @@ +trait BigNumTrait {} + +pub struct MyBigNum; + +impl crate::BigNumTrait for MyBigNum {} + +trait CurveParamsTrait +where + BigNum: BigNumTrait, +{ + // The difference between this and regression_7083 is that here + // this is a default method. + fn one() {} +} + +pub struct BN254Params; +impl CurveParamsTrait for BN254Params {} + +trait BigCurveTrait { + fn two(); +} + +pub struct BigCurve {} + +type BN254 = BigCurve; + +impl BigCurveTrait for BigCurve +where + BigNum: BigNumTrait, + CurveParams: CurveParamsTrait, +{ + fn two() { + let _ = CurveParams::one(); + } +} + +fn main() { + let _ = BN254::two(); +} diff --git a/test_programs/compile_success_empty/regression_7038_3/Nargo.toml b/test_programs/compile_success_empty/regression_7038_3/Nargo.toml new file mode 100644 index 00000000000..65bc946c559 --- /dev/null +++ b/test_programs/compile_success_empty/regression_7038_3/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_7038_3" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_7038_3/src/main.nr b/test_programs/compile_success_empty/regression_7038_3/src/main.nr new file mode 100644 index 00000000000..1b6bf0b72d5 --- /dev/null +++ b/test_programs/compile_success_empty/regression_7038_3/src/main.nr @@ -0,0 +1,40 @@ +trait BigNumTrait {} + +pub struct MyBigNum; + +impl crate::BigNumTrait for MyBigNum {} + +trait CurveParamsTrait { + // The difference between this and regression_7038 and regression_7038_2 is that + // here the where clause is on the method, not the trait + fn one() + where + BigNum: BigNumTrait; +} + +pub struct BN254Params; +impl CurveParamsTrait for BN254Params { + fn one() {} +} + +trait BigCurveTrait { + fn two(); +} + +pub struct BigCurve {} + +type BN254 = BigCurve; + +impl BigCurveTrait for BigCurve +where + BigNum: BigNumTrait, + CurveParams: CurveParamsTrait, +{ + fn two() { + let _ = CurveParams::one(); + } +} + +fn main() { + let _ = BN254::two(); +} diff --git a/test_programs/compile_success_empty/regression_7038_4/Nargo.toml b/test_programs/compile_success_empty/regression_7038_4/Nargo.toml new file mode 100644 index 00000000000..435c8094c70 --- /dev/null +++ b/test_programs/compile_success_empty/regression_7038_4/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_7038_4" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/regression_7038_4/src/main.nr b/test_programs/compile_success_empty/regression_7038_4/src/main.nr new file mode 100644 index 00000000000..524f05a5022 --- /dev/null +++ b/test_programs/compile_success_empty/regression_7038_4/src/main.nr @@ -0,0 +1,29 @@ +// This program is a reduction of regression_7038_3 that led to a monomorphizer crash +trait BigNumTrait {} + +trait CurveParamsTrait { + fn one() + where + BigNum: BigNumTrait; +} + +pub struct MyBigNum; + +impl BigNumTrait for MyBigNum {} + +pub struct Params; +impl CurveParamsTrait for Params { + + fn one() {} +} + +fn foo() +where + C: CurveParamsTrait, +{ + let _ = C::one(); +} + +fn main() { + foo::(); +} diff --git a/test_programs/compile_success_empty/ret_fn_ret_cl/Nargo.toml b/test_programs/compile_success_empty/ret_fn_ret_cl/Nargo.toml new file mode 100644 index 00000000000..4f778574417 --- /dev/null +++ b/test_programs/compile_success_empty/ret_fn_ret_cl/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "ret_fn_ret_cl" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/ret_fn_ret_cl/src/main.nr b/test_programs/compile_success_empty/ret_fn_ret_cl/src/main.nr new file mode 100644 index 00000000000..0e99a92585b --- /dev/null +++ b/test_programs/compile_success_empty/ret_fn_ret_cl/src/main.nr @@ -0,0 +1,31 @@ +fn f(x: Field) -> Field { + x + 1 +} + +fn ret_fn() -> fn(Field) -> Field { + f +} +// TODO: in the advanced implicitly generic function with closures branch +// which would support higher-order functions in a better way +// support returning closures: +// +// fn ret_closure() -> fn(Field) -> Field { +// let y = 1; +// let inner_closure = |z| -> Field{ +// z + y +// }; +// inner_closure +// } +fn ret_lambda() -> fn(Field) -> Field { + let cl = |z: Field| -> Field { z + 1 }; + cl +} + +fn main(x: Field) { + let result_fn = ret_fn(); + assert(result_fn(x) == x + 1); + // let result_closure = ret_closure(); + // assert(result_closure(x) == x + 1); + let result_lambda = ret_lambda(); + assert(result_lambda(x) == x + 1); +} diff --git a/test_programs/compile_success_empty/serialize/Nargo.toml b/test_programs/compile_success_empty/serialize/Nargo.toml new file mode 100644 index 00000000000..2cf87765b8a --- /dev/null +++ b/test_programs/compile_success_empty/serialize/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "serialize" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/serialize/src/main.nr b/test_programs/compile_success_empty/serialize/src/main.nr new file mode 100644 index 00000000000..66c79f9fc9d --- /dev/null +++ b/test_programs/compile_success_empty/serialize/src/main.nr @@ -0,0 +1,66 @@ +trait Serialize { + let Size: u32; + + // Note that Rust disallows referencing constants here! + fn serialize(self) -> [Field; Self::Size]; +} + +impl Serialize for (A, B) +where + A: Serialize, + B: Serialize, +{ + // let Size = ::Size + ::Size; + let Size: u32 = AS + BS; + + fn serialize(self: Self) -> [Field; Self::Size] { + let mut array: [Field; Self::Size] = std::mem::zeroed(); + let a = self.0.serialize(); + let b = self.1.serialize(); + + for i in 0..a.len() { + array[i] = a[i]; + } + for i in 0..b.len() { + array[i + a.len()] = b[i]; + } + array + } +} + +impl Serialize for [T; N] +where + T: Serialize, +{ + // let Size = ::Size * N; + let Size: u32 = TS * N; + + fn serialize(self: Self) -> [Field; Self::Size] { + let mut array: [Field; Self::Size] = std::mem::zeroed(); + let mut array_i = 0; + + for elem in self { + let elem_fields = elem.serialize(); + + for i in 0..elem_fields.len() { + array[array_i] = elem_fields[i]; + array_i += 1; + } + } + + array + } +} + +impl Serialize for Field { + let Size: u32 = 1; + + fn serialize(self) -> [Field; Self::Size] { + [self] + } +} + +fn main() { + let x = ((1, [2, 3, 4]), [5, 6, 7, 8]); + assert_eq(x.serialize().len(), 8); +} diff --git a/test_programs/compile_success_empty/simple_program_no_body/Nargo.toml b/test_programs/compile_success_empty/simple_program_no_body/Nargo.toml new file mode 100644 index 00000000000..13178336eea --- /dev/null +++ b/test_programs/compile_success_empty/simple_program_no_body/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "simple_program_no_body" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/simple_program_no_body/src/main.nr b/test_programs/compile_success_empty/simple_program_no_body/src/main.nr new file mode 100644 index 00000000000..8605ff1a9cc --- /dev/null +++ b/test_programs/compile_success_empty/simple_program_no_body/src/main.nr @@ -0,0 +1,9 @@ +// Tests a very simple program. +// +// The features being tested are: +// - Abi generation of private and public +// main parameters. +// +// This program will never fail since there are +// no assertions being applied. +fn main(_x: Field, _y: pub Field) {} diff --git a/test_programs/compile_success_empty/simple_range/Nargo.toml b/test_programs/compile_success_empty/simple_range/Nargo.toml new file mode 100644 index 00000000000..1db9099be7e --- /dev/null +++ b/test_programs/compile_success_empty/simple_range/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "simple_range" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/simple_range/src/main.nr b/test_programs/compile_success_empty/simple_range/src/main.nr new file mode 100644 index 00000000000..b7c319cfed4 --- /dev/null +++ b/test_programs/compile_success_empty/simple_range/src/main.nr @@ -0,0 +1,6 @@ +// Tests a very simple program. +// +// The features being tested is casting to an integer +fn main(x: Field) { + let _z = x as u32; +} 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_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..27339f812e7 --- /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/slice_join/Nargo.toml b/test_programs/compile_success_empty/slice_join/Nargo.toml new file mode 100644 index 00000000000..44be002efb4 --- /dev/null +++ b/test_programs/compile_success_empty/slice_join/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "slice_join" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/slice_join/src/main.nr b/test_programs/compile_success_empty/slice_join/src/main.nr new file mode 100644 index 00000000000..d65f8a4f040 --- /dev/null +++ b/test_programs/compile_success_empty/slice_join/src/main.nr @@ -0,0 +1,19 @@ +use std::append::Append; + +fn main() { + let slice = &[1, 2, 3, 4, 5]; + + let odds = slice.filter(|x| x % 2 == 1); + assert_eq(odds, &[1, 3, 5]); + + let odds_and_evens = append_three(odds, &[100], &[2, 4]); + assert_eq(odds_and_evens, &[1, 3, 5, 100, 2, 4]); +} + +fn append_three(one: T, two: T, three: T) -> T +where + T: Append, +{ + // The `T::empty()`s here should do nothing + T::empty().append(one).append(two).append(three).append(T::empty()) +} diff --git a/test_programs/compile_success_empty/specialization/Nargo.toml b/test_programs/compile_success_empty/specialization/Nargo.toml new file mode 100644 index 00000000000..aaccd85a444 --- /dev/null +++ b/test_programs/compile_success_empty/specialization/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "specialization" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/specialization/src/main.nr b/test_programs/compile_success_empty/specialization/src/main.nr new file mode 100644 index 00000000000..30116330a86 --- /dev/null +++ b/test_programs/compile_success_empty/specialization/src/main.nr @@ -0,0 +1,19 @@ +struct Foo {} + +impl Foo { + fn foo(_self: Self) -> Field { + 1 + } +} + +impl Foo { + fn foo(_self: Self) -> Field { + 2 + } +} + +fn main() { + let f1: Foo = Foo {}; + let f2: Foo = Foo {}; + assert(f1.foo() + f2.foo() == 3); +} diff --git a/test_programs/compile_success_empty/static_assert/Nargo.toml b/test_programs/compile_success_empty/static_assert/Nargo.toml new file mode 100644 index 00000000000..5dabd7803e3 --- /dev/null +++ b/test_programs/compile_success_empty/static_assert/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/static_assert/src/main.nr b/test_programs/compile_success_empty/static_assert/src/main.nr new file mode 100644 index 00000000000..fda310ba7eb --- /dev/null +++ b/test_programs/compile_success_empty/static_assert/src/main.nr @@ -0,0 +1,46 @@ +use std::static_assert; + +global GLOBAL_ONE: Field = 1; +global GLOBAL_TWO: Field = 2; +global GLOBAL_THREE: Field = GLOBAL_ONE + GLOBAL_TWO; + +// contents known at compile time +// length known at compile time +global GLOBAL_ARRAY_PAIR: [Field; 2] = [GLOBAL_ONE, GLOBAL_TWO]; +global GLOBAL_SLICE_PAIR: [Field] = &[GLOBAL_ONE, GLOBAL_TWO]; + +pub struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 + dynamic_two: Field, // == 2 +) { + // contents unknown at compile time + // length known at compile time + let dynamic_array_pair = [dynamic_one, dynamic_two]; + let dynamic_slice_pair = &[dynamic_one, dynamic_two]; + + static_assert(true, ""); + + static_assert(1 + 1 == 2, ""); + + let x = 2; + let y = 3; + let xy = x + y; + static_assert(xy == 5, ""); + + static_assert(3 == GLOBAL_THREE, ""); + + static_assert(GLOBAL_ARRAY_PAIR.len() == 2, ""); + static_assert(GLOBAL_SLICE_PAIR.len() == 2, ""); + + static_assert(dynamic_array_pair.len() == 2, ""); + static_assert(dynamic_slice_pair.len() == 2, ""); + + assert_constant([1, 2, dynamic_one].len() == 4); + static_assert([1, 2, dynamic_one].len() == 3, ""); +} diff --git a/test_programs/compile_success_empty/str_as_bytes/Nargo.toml b/test_programs/compile_success_empty/str_as_bytes/Nargo.toml new file mode 100644 index 00000000000..6b9bbd9b65f --- /dev/null +++ b/test_programs/compile_success_empty/str_as_bytes/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "str_as_bytes" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/str_as_bytes/src/main.nr b/test_programs/compile_success_empty/str_as_bytes/src/main.nr new file mode 100644 index 00000000000..1330924e501 --- /dev/null +++ b/test_programs/compile_success_empty/str_as_bytes/src/main.nr @@ -0,0 +1,17 @@ +fn main() { + let a = "hello"; + let b = a.as_bytes(); + assert(b[0] == 104); + assert(b[1] == 101); + assert(b[2] == 108); + assert(b[3] == 108); + assert(b[4] == 111); + assert(b.len() == 5); + let mut c = a.as_bytes_vec(); + assert(c.get(0) == 104); + assert(c.get(1) == 101); + assert(c.get(2) == 108); + assert(c.get(3) == 108); + assert(c.get(4) == 111); + assert(c.len() == 5); +} diff --git a/test_programs/compile_success_empty/struct_public_field/Nargo.toml b/test_programs/compile_success_empty/struct_public_field/Nargo.toml new file mode 100644 index 00000000000..37307b94af5 --- /dev/null +++ b/test_programs/compile_success_empty/struct_public_field/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "struct_public_field" +type = "bin" +authors = [""] + +[dependencies] +dependency = {path = "dependency"} \ No newline at end of file diff --git a/test_programs/compile_success_empty/struct_public_field/dependency/Nargo.toml b/test_programs/compile_success_empty/struct_public_field/dependency/Nargo.toml new file mode 100644 index 00000000000..2e471678a44 --- /dev/null +++ b/test_programs/compile_success_empty/struct_public_field/dependency/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "dependency" +type = "lib" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/struct_public_field/dependency/src/lib.nr b/test_programs/compile_success_empty/struct_public_field/dependency/src/lib.nr new file mode 100644 index 00000000000..0e9bd4bd9f8 --- /dev/null +++ b/test_programs/compile_success_empty/struct_public_field/dependency/src/lib.nr @@ -0,0 +1,4 @@ +pub struct Point { + pub x: Field, + pub y: Field, +} diff --git a/test_programs/compile_success_empty/struct_public_field/src/main.nr b/test_programs/compile_success_empty/struct_public_field/src/main.nr new file mode 100644 index 00000000000..c269c474de7 --- /dev/null +++ b/test_programs/compile_success_empty/struct_public_field/src/main.nr @@ -0,0 +1,8 @@ +use dependency::Point; + +fn main() { + let point = Point { x: 1, y: 2 }; + let _ = point.x; + let Point { x, y } = point; + let _ = (x, y); +} diff --git a/test_programs/compile_success_empty/to_bits/Nargo.toml b/test_programs/compile_success_empty/to_bits/Nargo.toml new file mode 100644 index 00000000000..ef47f3b4ba1 --- /dev/null +++ b/test_programs/compile_success_empty/to_bits/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "to_bits" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/compile_success_empty/to_bits/src/main.nr b/test_programs/compile_success_empty/to_bits/src/main.nr new file mode 100644 index 00000000000..dc2ff4be394 --- /dev/null +++ b/test_programs/compile_success_empty/to_bits/src/main.nr @@ -0,0 +1,21 @@ +fn main() { + let field = 1000; + let be_bits: [u1; 16] = field.to_be_bits(); + let le_bits: [u1; 16] = field.to_le_bits(); + + for i in 0..16 { + let x = be_bits[i]; + let y = le_bits[15 - i]; + assert(x == y); + } + + let x = 3; + let be_bits_x: [u1; 4] = x.to_be_bits(); + let le_bits_x: [u1; 4] = x.to_le_bits(); + + for i in 0..4 { + let be_bit = be_bits_x[i]; + let le_bit = le_bits_x[3 - i]; + assert(be_bit == le_bit); + } +} diff --git a/test_programs/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml b/test_programs/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml new file mode 100644 index 00000000000..bd31596297a --- /dev/null +++ b/test_programs/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "trait_allowed_item_name_matches" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/trait_allowed_item_name_matches/src/main.nr b/test_programs/compile_success_empty/trait_allowed_item_name_matches/src/main.nr new file mode 100644 index 00000000000..f32445202b7 --- /dev/null +++ b/test_programs/compile_success_empty/trait_allowed_item_name_matches/src/main.nr @@ -0,0 +1,25 @@ +pub trait Trait1 { + // types and consts with the same name are allowed + type Tralala; + let Tralala: u32; +} + +pub trait Trait2 { + // consts and types with the same name are allowed + let Tralala: u32; + type Tralala; +} + +pub trait Trait3 { + // types and functions with the same name are allowed + type Tralala; + fn Tralala(); +} + +pub trait Trait4 { + // functions and types with the same name are allowed + fn Tralala(); + type Tralala; +} + +fn main() {} diff --git a/test_programs/compile_success_empty/trait_as_constraint/Nargo.toml b/test_programs/compile_success_empty/trait_as_constraint/Nargo.toml new file mode 100644 index 00000000000..907b5ce09ed --- /dev/null +++ b/test_programs/compile_success_empty/trait_as_constraint/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "trait_as_constraint" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/trait_as_constraint/src/main.nr b/test_programs/compile_success_empty/trait_as_constraint/src/main.nr new file mode 100644 index 00000000000..b516376aae5 --- /dev/null +++ b/test_programs/compile_success_empty/trait_as_constraint/src/main.nr @@ -0,0 +1,9 @@ +#[test_as_constraint] +pub trait Foo {} + +comptime fn test_as_constraint(t: TraitDefinition) { + let constraint = t.as_trait_constraint(); + assert(constraint == constraint); +} + +fn main() {} diff --git a/test_programs/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml b/test_programs/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml new file mode 100644 index 00000000000..79d78c1aa51 --- /dev/null +++ b/test_programs/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "trait_associated_member_names_clashes" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/trait_associated_member_names_clashes/src/main.nr b/test_programs/compile_success_empty/trait_associated_member_names_clashes/src/main.nr new file mode 100644 index 00000000000..953ee321b47 --- /dev/null +++ b/test_programs/compile_success_empty/trait_associated_member_names_clashes/src/main.nr @@ -0,0 +1,35 @@ +trait Trait1 { + fn tralala() -> Field; +} + +trait Trait2 { + fn tralala() -> Field; +} + +pub struct Struct1 {} + +impl Struct1 { + fn tralala() -> Field { + 123456 + } +} + +impl Trait1 for Struct1 { + fn tralala() -> Field { + 111111 + } +} + +impl Trait2 for Struct1 { + fn tralala() -> Field { + 222222 + } +} + +fn main() { + // the struct impl takes priority over trait methods + assert(Struct1::tralala() == 123456); + // TODO: uncomment these, once we support the :: syntax + //assert(::tralala() == 111111); + //assert(::tralala() == 222222); +} diff --git a/test_programs/compile_success_empty/trait_attribute/Nargo.toml b/test_programs/compile_success_empty/trait_attribute/Nargo.toml new file mode 100644 index 00000000000..c72fe5e3e89 --- /dev/null +++ b/test_programs/compile_success_empty/trait_attribute/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "trait_attribute" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/trait_attribute/src/main.nr b/test_programs/compile_success_empty/trait_attribute/src/main.nr new file mode 100644 index 00000000000..87f4893e3e5 --- /dev/null +++ b/test_programs/compile_success_empty/trait_attribute/src/main.nr @@ -0,0 +1,19 @@ +#[trait_attr] +trait Foo { + fn foo(self) -> Self; +} + +comptime fn trait_attr(_t: TraitDefinition) -> Quoted { + quote { + impl Foo for Field { + fn foo(self) -> Self { + self + 1 + } + } + } +} + +fn main() { + assert_eq(1.foo(), 2); + assert_eq(10.foo(), 11); +} diff --git a/test_programs/compile_success_empty/trait_call_full_path/Nargo.toml b/test_programs/compile_success_empty/trait_call_full_path/Nargo.toml new file mode 100644 index 00000000000..f6d20fc3e32 --- /dev/null +++ b/test_programs/compile_success_empty/trait_call_full_path/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_call_full_path" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/trait_call_full_path/src/main.nr b/test_programs/compile_success_empty/trait_call_full_path/src/main.nr new file mode 100644 index 00000000000..aea0f436dce --- /dev/null +++ b/test_programs/compile_success_empty/trait_call_full_path/src/main.nr @@ -0,0 +1,20 @@ +mod foo { + pub trait Trait { + fn me(self) -> Self; + } + + impl Trait for Field { + fn me(self) -> Self { + self + } + } +} + +use foo::Trait; +use foo::Trait::me; + +fn main(x: Field) { + let _ = foo::Trait::me(x); + let _ = Trait::me(x); + let _ = me(x); +} diff --git a/test_programs/compile_success_empty/trait_call_in_global/Nargo.toml b/test_programs/compile_success_empty/trait_call_in_global/Nargo.toml new file mode 100644 index 00000000000..005fec5bf36 --- /dev/null +++ b/test_programs/compile_success_empty/trait_call_in_global/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_call_in_global" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/trait_call_in_global/src/main.nr b/test_programs/compile_success_empty/trait_call_in_global/src/main.nr new file mode 100644 index 00000000000..775cb5f3b7d --- /dev/null +++ b/test_programs/compile_success_empty/trait_call_in_global/src/main.nr @@ -0,0 +1,5 @@ +global s: BoundedVec = From::from([0]); + +fn main() { + let _ = s; +} diff --git a/test_programs/compile_success_empty/trait_default_implementation/Nargo.toml b/test_programs/compile_success_empty/trait_default_implementation/Nargo.toml new file mode 100644 index 00000000000..938e224ec02 --- /dev/null +++ b/test_programs/compile_success_empty/trait_default_implementation/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_default_implementation" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/trait_default_implementation/src/main.nr b/test_programs/compile_success_empty/trait_default_implementation/src/main.nr new file mode 100644 index 00000000000..ecfa6da0818 --- /dev/null +++ b/test_programs/compile_success_empty/trait_default_implementation/src/main.nr @@ -0,0 +1,23 @@ +trait MyDefault { + fn my_default(x: Field, y: Field) -> Self; + + fn method2(x: Field) -> Field { + x + } +} + +struct Foo { + bar: Field, + array: [Field; 2], +} + +impl MyDefault for Foo { + fn my_default(x: Field, y: Field) -> Self { + Self { bar: x, array: [x, y] } + } +} + +fn main(x: Field) { + let first = Foo::method2(x); + assert(first == x); +} diff --git a/test_programs/compile_success_empty/trait_default_method_uses_op/Nargo.toml b/test_programs/compile_success_empty/trait_default_method_uses_op/Nargo.toml new file mode 100644 index 00000000000..d8b882c1696 --- /dev/null +++ b/test_programs/compile_success_empty/trait_default_method_uses_op/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "trait_default_method_uses_op" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/trait_default_method_uses_op/src/main.nr b/test_programs/compile_success_empty/trait_default_method_uses_op/src/main.nr new file mode 100644 index 00000000000..415f36fe207 --- /dev/null +++ b/test_programs/compile_success_empty/trait_default_method_uses_op/src/main.nr @@ -0,0 +1,7 @@ +pub trait Foo: Eq { + fn foo(self) -> bool { + self == self + } +} + +fn main() {} diff --git a/test_programs/compile_success_empty/trait_function_calls/Nargo.toml b/test_programs/compile_success_empty/trait_function_calls/Nargo.toml new file mode 100644 index 00000000000..1bb7522d6e1 --- /dev/null +++ b/test_programs/compile_success_empty/trait_function_calls/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "trait_function_calls" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/trait_function_calls/src/main.nr b/test_programs/compile_success_empty/trait_function_calls/src/main.nr new file mode 100644 index 00000000000..bdc4a3d8c90 --- /dev/null +++ b/test_programs/compile_success_empty/trait_function_calls/src/main.nr @@ -0,0 +1,786 @@ +// a more thorough test for trait function/method calls from within trait function/method calls +// This tests all combinations of caller+callee pairs. For each of these, the following combination of properties are tried: +// *) method (has self parameter) vs function (no self parameter) +// *) default vs overriden vs overriden (no default) +// test order is: +// 1) trait method -> trait method +// 1a) trait default method -> trait default method +// 1b) trait default method -> trait overriden method +// 1c) trait default method -> trait overriden (no default) method +// 1d) trait overriden method -> trait default method +// 1e) trait overriden method -> trait overriden method +// 1f) trait overriden method -> trait overriden (no default) method +// 1g) trait overriden (no default) method -> trait default method +// 1h) trait overriden (no default) method -> trait overriden method +// 1i) trait overriden (no default) method -> trait overriden (no default) method +// 2) trait method -> trait function +// 2a) - subcases are the same as the above +// ... +// 2i) +// 3{a..i}) trait function -> trait method +// 4{a..i}) trait function -> trait function +// 1) trait method -> trait method +// 1a) trait default method -> trait default method +trait Trait1a { + fn trait_method1(self) -> Field { + self.trait_method2() * 7892 - self.vl() + } + fn trait_method2(self) -> Field { + let _ = self; + 43278 + } + fn vl(self) -> Field; +} +struct Struct1a { + vl: Field, +} +impl Trait1a for Struct1a { + fn vl(self) -> Field { + self.vl + } +} +// 1b) trait default method -> trait overriden method +trait Trait1b { + fn trait_method1(self) -> Field { + self.trait_method2() * 2832 - self.vl() + } + fn trait_method2(self) -> Field { + let _ = self; + 9323 + } + fn vl(self) -> Field; +} +struct Struct1b { + vl: Field, +} +impl Trait1b for Struct1b { + fn trait_method2(self) -> Field { + let _ = self; + 2394 + } + fn vl(self) -> Field { + self.vl + } +} +// 1c) trait default method -> trait overriden (no default) method +trait Trait1c { + fn trait_method1(self) -> Field { + self.trait_method2() * 7635 - self.vl() + } + fn trait_method2(self) -> Field; + fn vl(self) -> Field; +} +struct Struct1c { + vl: Field, +} +impl Trait1c for Struct1c { + fn trait_method2(self) -> Field { + let _ = self; + 5485 + } + fn vl(self) -> Field { + self.vl + } +} +// 1d) trait overriden method -> trait default method +trait Trait1d { + fn trait_method1(self) -> Field { + self.trait_method2() * 2825 - self.vl() + } + fn trait_method2(self) -> Field { + let _ = self; + 29341 + } + fn vl(self) -> Field; +} +struct Struct1d { + vl: Field, +} +impl Trait1d for Struct1d { + fn trait_method1(self) -> Field { + self.trait_method2() * 9342 - self.vl + } + fn vl(self) -> Field { + self.vl + } +} +// 1e) trait overriden method -> trait overriden method +trait Trait1e { + fn trait_method1(self) -> Field { + self.trait_method2() * 85465 - self.vl() + } + fn trait_method2(self) -> Field { + let _ = self; + 2381 + } + fn vl(self) -> Field; +} +struct Struct1e { + vl: Field, +} +impl Trait1e for Struct1e { + fn trait_method1(self) -> Field { + self.trait_method2() * 47324 - self.vl + } + fn trait_method2(self) -> Field { + let _ = self; + 58945 + } + fn vl(self) -> Field { + self.vl + } +} +// 1f) trait overriden method -> trait overriden (no default) method +trait Trait1f { + fn trait_method1(self) -> Field { + self.trait_method2() * 43257 - self.vl() + } + fn trait_method2(self) -> Field; + fn vl(self) -> Field; +} +struct Struct1f { + vl: Field, +} +impl Trait1f for Struct1f { + fn trait_method1(self) -> Field { + self.trait_method2() * 34875 - self.vl + } + fn trait_method2(self) -> Field { + let _ = self; + 5748 + } + fn vl(self) -> Field { + self.vl + } +} +// 1g) trait overriden (no default) method -> trait default method +trait Trait1g { + fn trait_method1(self) -> Field; + fn trait_method2(self) -> Field { + let _ = self; + 37845 + } +} +struct Struct1g { + vl: Field, +} +impl Trait1g for Struct1g { + fn trait_method1(self) -> Field { + self.trait_method2() * 7854 - self.vl + } +} +// 1h) trait overriden (no default) method -> trait overriden method +trait Trait1h { + fn trait_method1(self) -> Field; + fn trait_method2(self) -> Field { + let _ = self; + 7823 + } +} +struct Struct1h { + vl: Field, +} +impl Trait1h for Struct1h { + fn trait_method1(self) -> Field { + self.trait_method2() * 3482 - self.vl + } + fn trait_method2(self) -> Field { + let _ = self; + 8542 + } +} +// 1i) trait overriden (no default) method -> trait overriden (no default) method +trait Trait1i { + fn trait_method1(self) -> Field; + fn trait_method2(self) -> Field; +} +struct Struct1i { + vl: Field, +} +impl Trait1i for Struct1i { + fn trait_method1(self) -> Field { + self.trait_method2() * 23478 - self.vl + } + fn trait_method2(self) -> Field { + let _ = self; + 98543 + } +} +// 2) trait method -> trait function +// 2a) trait default method -> trait default function +trait Trait2a { + fn trait_method1(self) -> Field { + Self::trait_function2() * 2385 - self.vl() + } + fn trait_function2() -> Field { + 7843 + } + fn vl(self) -> Field; +} +struct Struct2a { + vl: Field, +} +impl Trait2a for Struct2a { + fn vl(self) -> Field { + self.vl + } +} +// 2b) trait default method -> trait overriden function +trait Trait2b { + fn trait_method1(self) -> Field { + Self::trait_function2() * 6583 - self.vl() + } + fn trait_function2() -> Field { + 3752 + } + fn vl(self) -> Field; +} +struct Struct2b { + vl: Field, +} +impl Trait2b for Struct2b { + fn trait_function2() -> Field { + 8477 + } + fn vl(self) -> Field { + self.vl + } +} +// 2c) trait default method -> trait overriden (no default) function +trait Trait2c { + fn trait_method1(self) -> Field { + Self::trait_function2() * 2831 - self.vl() + } + fn trait_function2() -> Field; + fn vl(self) -> Field; +} +struct Struct2c { + vl: Field, +} +impl Trait2c for Struct2c { + fn trait_function2() -> Field { + 8342 + } + fn vl(self) -> Field { + self.vl + } +} +// 2d) trait overriden method -> trait default function +trait Trait2d { + fn trait_method1(self) -> Field { + Self::trait_function2() * 924 - self.vl() + } + fn trait_function2() -> Field { + 384 + } + fn vl(self) -> Field; +} +struct Struct2d { + vl: Field, +} +impl Trait2d for Struct2d { + fn trait_method1(self) -> Field { + Self::trait_function2() * 3984 - self.vl + } + fn vl(self) -> Field { + self.vl + } +} +// 2e) trait overriden method -> trait overriden function +trait Trait2e { + fn trait_method1(self) -> Field { + Self::trait_function2() * 3642 - self.vl() + } + fn trait_function2() -> Field { + 97342 + } + fn vl(self) -> Field; +} +struct Struct2e { + vl: Field, +} +impl Trait2e for Struct2e { + fn trait_method1(self) -> Field { + Self::trait_function2() * 7363 - self.vl + } + fn trait_function2() -> Field { + 39400 + } + fn vl(self) -> Field { + self.vl + } +} +// 2f) trait overriden method -> trait overriden (no default) function +trait Trait2f { + fn trait_method1(self) -> Field { + Self::trait_function2() * 2783 - self.vl() + } + fn trait_function2() -> Field; + fn vl(self) -> Field; +} +struct Struct2f { + vl: Field, +} +impl Trait2f for Struct2f { + fn trait_method1(self) -> Field { + Self::trait_function2() * 6362 - self.vl + } + fn trait_function2() -> Field { + 72311 + } + fn vl(self) -> Field { + self.vl + } +} +// 2g) trait overriden (no default) method -> trait default function +trait Trait2g { + fn trait_method1(self) -> Field; + fn trait_function2() -> Field { + 19273 + } +} +struct Struct2g { + vl: Field, +} +impl Trait2g for Struct2g { + fn trait_method1(self) -> Field { + Self::trait_function2() * 9123 - self.vl + } +} +// 2h) trait overriden (no default) method -> trait overriden function +trait Trait2h { + fn trait_method1(self) -> Field; + fn trait_function2() -> Field { + 1281 + } +} +struct Struct2h { + vl: Field, +} +impl Trait2h for Struct2h { + fn trait_method1(self) -> Field { + Self::trait_function2() * 4833 - self.vl + } + fn trait_function2() -> Field { + 5335 + } +} +// 2i) trait overriden (no default) method -> trait overriden (no default) function +trait Trait2i { + fn trait_method1(self) -> Field; + fn trait_function2() -> Field; +} +struct Struct2i { + vl: Field, +} +impl Trait2i for Struct2i { + fn trait_method1(self) -> Field { + Self::trait_function2() * 2291 - self.vl + } + fn trait_function2() -> Field { + 3322 + } +} +// 3 trait function -> trait method +// 3a) trait default function -> trait default method +trait Trait3a { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 8344 - b.vl() + a + } + fn trait_method2(self) -> Field { + let _ = self; + 19212 + } + fn vl(self) -> Field; +} +struct Struct3a { + vl: Field, +} +impl Trait3a for Struct3a { + fn vl(self) -> Field { + self.vl + } +} +// 3b) trait default function -> trait overriden method +trait Trait3b { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 9233 - b.vl() + a + } + fn trait_method2(self) -> Field { + let _ = self; + 9111 + } + fn vl(self) -> Field; +} +struct Struct3b { + vl: Field, +} +impl Trait3b for Struct3b { + fn trait_method2(self) -> Field { + let _ = self; + 2392 + } + fn vl(self) -> Field { + self.vl + } +} +// 3c) trait default function -> trait overriden (no default) method +trait Trait3c { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 2822 - b.vl() + a + } + fn trait_method2(self) -> Field; + fn vl(self) -> Field; +} +struct Struct3c { + vl: Field, +} +impl Trait3c for Struct3c { + fn trait_method2(self) -> Field { + let _ = self; + 7743 + } + fn vl(self) -> Field { + self.vl + } +} +// 3d) trait overriden function -> trait default method +trait Trait3d { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 291 - b.vl() + a + } + fn trait_method2(self) -> Field { + let _ = self; + 3328 + } + fn vl(self) -> Field; +} +struct Struct3d { + vl: Field, +} +impl Trait3d for Struct3d { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 4933 - b.vl + a + } + fn vl(self) -> Field { + self.vl + } +} +// 3e) trait overriden function -> trait overriden method +trait Trait3e { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 71231 - b.vl() + a + } + fn trait_method2(self) -> Field { + let _ = self; + 373 + } + fn vl(self) -> Field; +} +struct Struct3e { + vl: Field, +} +impl Trait3e for Struct3e { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 81232 - b.vl + a + } + fn trait_method2(self) -> Field { + let _ = self; + 80002 + } + fn vl(self) -> Field { + self.vl + } +} +// 3f) trait overriden function -> trait overriden (no default) method +trait Trait3f { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 28223 - b.vl() + a + } + fn trait_method2(self) -> Field; + fn vl(self) -> Field; +} +struct Struct3f { + vl: Field, +} +impl Trait3f for Struct3f { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 29223 - b.vl + a + } + fn trait_method2(self) -> Field { + let _ = self; + 63532 + } + fn vl(self) -> Field { + self.vl + } +} +// 3g) trait overriden (no default) function -> trait default method +trait Trait3g { + fn trait_function1(a: Field, b: Self) -> Field; + fn trait_method2(self) -> Field { + let _ = self; + 8887 + } +} +struct Struct3g { + vl: Field, +} +impl Trait3g for Struct3g { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 31337 - b.vl + a + } +} +// 3h) trait overriden (no default) function -> trait overriden method +trait Trait3h { + fn trait_function1(a: Field, b: Self) -> Field; + fn trait_method2(self) -> Field { + let _ = self; + 293 + } +} +struct Struct3h { + vl: Field, +} +impl Trait3h for Struct3h { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 74747 - b.vl + a + } + fn trait_method2(self) -> Field { + let _ = self; + 6283 + } +} +// 3i) trait overriden (no default) function -> trait overriden (no default) method +trait Trait3i { + fn trait_function1(a: Field, b: Self) -> Field; + fn trait_method2(self) -> Field; +} +struct Struct3i { + vl: Field, +} +impl Trait3i for Struct3i { + fn trait_function1(a: Field, b: Self) -> Field { + b.trait_method2() * 1237 - b.vl + a + } + fn trait_method2(self) -> Field { + let _ = self; + 84352 + } +} +// 4) trait function -> trait function +// 4a) trait default function -> trait default function +trait Trait4a { + fn trait_function1() -> Field { + Self::trait_function2() * 3842 + } + fn trait_function2() -> Field { + 2932 + } +} +pub struct Struct4a { + vl: Field, +} +impl Trait4a for Struct4a {} +// 4b) trait default function -> trait overriden function +trait Trait4b { + fn trait_function1() -> Field { + Self::trait_function2() * 3842 + } + fn trait_function2() -> Field { + 2932 + } +} +pub struct Struct4b { + vl: Field, +} +impl Trait4b for Struct4b { + fn trait_function2() -> Field { + 9353 + } +} +// 4c) trait default function -> trait overriden (no default) function +trait Trait4c { + fn trait_function1() -> Field { + Self::trait_function2() * 7832 + } + fn trait_function2() -> Field; +} +pub struct Struct4c { + vl: Field, +} +impl Trait4c for Struct4c { + fn trait_function2() -> Field { + 2928 + } +} +// 4d) trait overriden function -> trait default function +trait Trait4d { + fn trait_function1() -> Field { + Self::trait_function2() * 2283 + } + fn trait_function2() -> Field { + 9332 + } +} +pub struct Struct4d { + vl: Field, +} +impl Trait4d for Struct4d { + fn trait_function1() -> Field { + Self::trait_function2() * 8374 + } +} +// 4e) trait overriden function -> trait overriden function +trait Trait4e { + fn trait_function1() -> Field { + Self::trait_function2() * 94329 + } + fn trait_function2() -> Field { + 28328 + } +} +pub struct Struct4e { + vl: Field, +} +impl Trait4e for Struct4e { + fn trait_function1() -> Field { + Self::trait_function2() * 12323 + } + fn trait_function2() -> Field { + 38434 + } +} +// 4f) trait overriden function -> trait overriden (no default) function +trait Trait4f { + fn trait_function1() -> Field { + Self::trait_function2() * 23723 + } + fn trait_function2() -> Field; +} +pub struct Struct4f { + vl: Field, +} +impl Trait4f for Struct4f { + fn trait_function1() -> Field { + Self::trait_function2() * 21392 + } + fn trait_function2() -> Field { + 4394 + } +} +// 4g) trait overriden (no default) function -> trait default function +trait Trait4g { + fn trait_function1() -> Field; + fn trait_function2() -> Field { + 2932 + } +} +pub struct Struct4g { + vl: Field, +} +impl Trait4g for Struct4g { + fn trait_function1() -> Field { + Self::trait_function2() * 3345 + } +} +// 4h) trait overriden (no default) function -> trait overriden function +trait Trait4h { + fn trait_function1() -> Field; + fn trait_function2() -> Field { + 5756 + } +} +pub struct Struct4h { + vl: Field, +} +impl Trait4h for Struct4h { + fn trait_function1() -> Field { + Self::trait_function2() * 6478 + } + fn trait_function2() -> Field { + 5435 + } +} +// 4i) trait overriden (no default) function -> trait overriden (no default) function +trait Trait4i { + fn trait_function1() -> Field; + fn trait_function2() -> Field; +} +pub struct Struct4i { + vl: Field, +} +impl Trait4i for Struct4i { + fn trait_function1() -> Field { + Self::trait_function2() * 8239 + } + fn trait_function2() -> Field { + 2032 + } +} + +fn main() { + let t1a = Struct1a { vl: 1234 }; + assert(t1a.trait_method1() == 341548742); + let t1b = Struct1b { vl: 4444 }; + assert(t1b.trait_method1() == 6775364); + let t1c = Struct1c { vl: 3946 }; + assert(t1c.trait_method1() == 41874029); + let t1d = Struct1d { vl: 9234 }; + assert(t1d.trait_method1() == 274094388); + let t1e = Struct1e { vl: 5438 }; + assert(t1e.trait_method1() == 2789507742); + let t1f = Struct1f { vl: 6237 }; + assert(t1f.trait_method1() == 200455263); + let t1g = Struct1g { vl: 43587 }; + assert(t1g.trait_method1() == 297191043); + let t1h = Struct1h { vl: 3984 }; + assert(t1h.trait_method1() == 29739260); + let t1i = Struct1i { vl: 9234 }; + assert(t1i.trait_method1() == 2313583320); + let t2a = Struct2a { vl: 4362 }; + assert(t2a.trait_method1() == 18701193); + let t2b = Struct2b { vl: 8347 }; + assert(t2b.trait_method1() == 55795744); + let t2c = Struct2c { vl: 1923 }; + assert(t2c.trait_method1() == 23614279); + let t2d = Struct2d { vl: 92384 }; + assert(t2d.trait_method1() == 1437472); + let t2e = Struct2e { vl: 83943 }; + assert(t2e.trait_method1() == 290018257); + let t2f = Struct2f { vl: 8237 }; + assert(t2f.trait_method1() == 460034345); + let t2g = Struct2g { vl: 1232 }; + assert(t2g.trait_method1() == 175826347); + let t2h = Struct2h { vl: 7222 }; + assert(t2h.trait_method1() == 25776833); + let t2i = Struct2i { vl: 1821 }; + assert(t2i.trait_method1() == 7608881); + let t3a = Struct3a { vl: 93248 }; + assert(Struct3a::trait_function1(5, t3a) == 160211685); + let t3b = Struct3b { vl: 76763 }; + assert(Struct3b::trait_function1(62, t3b) == 22008635); + let t3c = Struct3c { vl: 3833 }; + assert(Struct3c::trait_function1(25, t3c) == 21846938); + let t3d = Struct3d { vl: 5645 }; + assert(Struct3d::trait_function1(73, t3d) == 16411452); + let t3e = Struct3e { vl: 22912 }; + assert(Struct3e::trait_function1(92, t3e) == 6498699644); + let t3f = Struct3f { vl: 3256 }; + assert(Struct3f::trait_function1(77, t3f) == 1856592457); + let t3g = Struct3g { vl: 22832 }; + assert(Struct3g::trait_function1(23, t3g) == 278469110); + let t3h = Struct3h { vl: 4933 }; + assert(Struct3h::trait_function1(17, t3h) == 469630485); + let t3i = Struct3i { vl: 39432 }; + assert(Struct3i::trait_function1(54, t3i) == 104304046); + assert(Struct4a::trait_function1() == 11264744); + assert(Struct4b::trait_function1() == 35934226); + assert(Struct4c::trait_function1() == 22932096); + assert(Struct4d::trait_function1() == 78146168); + assert(Struct4e::trait_function1() == 473622182); + assert(Struct4f::trait_function1() == 93996448); + assert(Struct4g::trait_function1() == 9807540); + assert(Struct4h::trait_function1() == 35207930); + assert(Struct4i::trait_function1() == 16741648); +} diff --git a/test_programs/compile_success_empty/trait_generics/Nargo.toml b/test_programs/compile_success_empty/trait_generics/Nargo.toml new file mode 100644 index 00000000000..7fdd5975541 --- /dev/null +++ b/test_programs/compile_success_empty/trait_generics/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "trait_generics" +type = "bin" +authors = [""] +compiler_version = ">=0.22.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/trait_generics/src/main.nr b/test_programs/compile_success_empty/trait_generics/src/main.nr new file mode 100644 index 00000000000..08302ded68c --- /dev/null +++ b/test_programs/compile_success_empty/trait_generics/src/main.nr @@ -0,0 +1,69 @@ +fn main() { + let xs: [Field; 1] = [3]; + let ys: [u32; 1] = [3]; + foo(xs, ys); + + assert_eq(15, sum(Data { a: 5, b: 10 })); + assert_eq(15, sum_static(Data { a: 5, b: 10 })); +} + +fn foo(x: T, u: U) +where + T: MyInto, + U: Eq, +{ + assert(x.into() == u); +} + +trait MyInto { + fn into(self) -> T; +} + +impl MyInto<[U; N]> for [T; N] +where + T: MyInto, +{ + fn into(self) -> [U; N] { + self.map(|x: T| x.into()) + } +} + +impl MyInto for Field { + fn into(self) -> u32 { + self as u32 + } +} + +/// Serialize example + +trait Serializable { + fn serialize(self) -> [Field; N]; +} + +struct Data { + a: Field, + b: Field, +} + +impl Serializable<2> for Data { + fn serialize(self) -> [Field; 2] { + [self.a, self.b] + } +} + +fn sum(data: T) -> Field +where + T: Serializable, +{ + let serialized = data.serialize(); + serialized.fold(0, |acc, elem| acc + elem) +} + +// Test static trait method syntax +fn sum_static(data: T) -> Field +where + T: Serializable, +{ + let serialized = Serializable::serialize(data); + serialized.fold(0, |acc, elem| acc + elem) +} diff --git a/test_programs/compile_success_empty/trait_impl_generics/Nargo.toml b/test_programs/compile_success_empty/trait_impl_generics/Nargo.toml new file mode 100644 index 00000000000..b10b5dab6aa --- /dev/null +++ b/test_programs/compile_success_empty/trait_impl_generics/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_impl_generics" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/trait_impl_generics/src/main.nr b/test_programs/compile_success_empty/trait_impl_generics/src/main.nr new file mode 100644 index 00000000000..33a086912d6 --- /dev/null +++ b/test_programs/compile_success_empty/trait_impl_generics/src/main.nr @@ -0,0 +1,69 @@ +struct Empty {} + +trait Foo { + fn foo(self) -> u32; +} + +impl Foo for Empty { + fn foo(_self: Self) -> u32 { + 32 + } +} + +impl Foo for Empty { + fn foo(_self: Self) -> u32 { + 64 + } +} + +fn main() { + let x: Empty = Empty {}; + let y: Empty = Empty {}; + let z = Empty {}; + + assert(x.foo() == 32); + assert(y.foo() == 64); + // Types matching multiple impls will currently choose + // the first matching one instead of erroring + assert(z.foo() == 32); + + call_impl_with_generic_struct(); + call_impl_with_generic_function(); +} +// Ensure we can call a generic impl +fn call_impl_with_generic_struct() { + let x: u8 = 7; + let y: i8 = 8; + let s2_u8 = S2 { x }; + let s2_i8 = S2 { x: y }; + assert(s2_u8.t2().x == 7); + assert(s2_i8.t2().x == 8); +} + +trait T2 { + fn t2(self) -> Self; +} + +struct S2 { + x: T, +} + +impl T2 for S2 { + fn t2(self) -> Self { + self + } +} + +fn call_impl_with_generic_function() { + assert(3.t3(7) == 7); +} + +trait T3 { + fn t3(self, x: T) -> T; +} + +impl T3 for u32 { + fn t3(_self: Self, y: U) -> U { + y + } +} diff --git a/test_programs/compile_success_empty/trait_impl_with_where_clause/Nargo.toml b/test_programs/compile_success_empty/trait_impl_with_where_clause/Nargo.toml new file mode 100644 index 00000000000..672569634ea --- /dev/null +++ b/test_programs/compile_success_empty/trait_impl_with_where_clause/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_impl_with_where_clause" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/trait_impl_with_where_clause/src/main.nr b/test_programs/compile_success_empty/trait_impl_with_where_clause/src/main.nr new file mode 100644 index 00000000000..6fa194f2520 --- /dev/null +++ b/test_programs/compile_success_empty/trait_impl_with_where_clause/src/main.nr @@ -0,0 +1,30 @@ +fn main() { + let array: [Field; 3] = [1, 2, 3]; + assert(array.my_eq(array)); + // Ensure this still works if we have to infer the type of the integer literals + let array = [1, 2, 3]; + assert(array.my_eq(array)); +} + +trait MyEq { + fn my_eq(self, other: Self) -> bool; +} + +impl MyEq for [T; 3] +where + T: MyEq, +{ + fn my_eq(self, other: Self) -> bool { + let mut ret = true; + for i in 0..self.len() { + ret &= self[i].my_eq(other[i]); + } + ret + } +} + +impl MyEq for Field { + fn my_eq(self, other: Field) -> bool { + self == other + } +} diff --git a/test_programs/compile_success_empty/trait_inheritance/Nargo.toml b/test_programs/compile_success_empty/trait_inheritance/Nargo.toml new file mode 100644 index 00000000000..b8390fc800d --- /dev/null +++ b/test_programs/compile_success_empty/trait_inheritance/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "trait_inheritance" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/trait_inheritance/src/main.nr b/test_programs/compile_success_empty/trait_inheritance/src/main.nr new file mode 100644 index 00000000000..1d17d386189 --- /dev/null +++ b/test_programs/compile_success_empty/trait_inheritance/src/main.nr @@ -0,0 +1,33 @@ +trait Foo { + fn foo(self) -> Field; +} + +trait Bar: Foo { + fn bar(self) -> Field { + self.foo() + 1 + } + + fn baz(self) -> Field; +} + +struct Struct { + x: Field, +} + +impl Foo for Struct { + fn foo(self) -> Field { + self.x + } +} + +impl Bar for Struct { + fn baz(self) -> Field { + self.foo() + 2 + } +} + +fn main() { + let s = Struct { x: 1 }; + assert_eq(s.bar(), 2); + assert_eq(s.baz(), 3); +} diff --git a/test_programs/compile_success_empty/trait_method_mut_self/Nargo.toml b/test_programs/compile_success_empty/trait_method_mut_self/Nargo.toml new file mode 100644 index 00000000000..d2fe9e8e137 --- /dev/null +++ b/test_programs/compile_success_empty/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/compile_success_empty/trait_method_mut_self/src/main.nr b/test_programs/compile_success_empty/trait_method_mut_self/src/main.nr new file mode 100644 index 00000000000..aa0baab7f89 --- /dev/null +++ b/test_programs/compile_success_empty/trait_method_mut_self/src/main.nr @@ -0,0 +1,83 @@ +use std::hash::Hasher; +use 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/compile_success_empty/trait_multi_module_test/Nargo.toml b/test_programs/compile_success_empty/trait_multi_module_test/Nargo.toml new file mode 100644 index 00000000000..efa176099cf --- /dev/null +++ b/test_programs/compile_success_empty/trait_multi_module_test/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_multi_module_test" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/trait_multi_module_test/src/main.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/main.nr new file mode 100644 index 00000000000..77c30ce602b --- /dev/null +++ b/test_programs/compile_success_empty/trait_multi_module_test/src/main.nr @@ -0,0 +1,8 @@ +mod module1; +mod module2; +mod module3; +mod module4; +mod module5; +mod module6; + +fn main() {} diff --git a/test_programs/compile_success_empty/trait_multi_module_test/src/module1.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module1.nr new file mode 100644 index 00000000000..8eaeafa5207 --- /dev/null +++ b/test_programs/compile_success_empty/trait_multi_module_test/src/module1.nr @@ -0,0 +1 @@ +pub trait MyTrait {} diff --git a/test_programs/compile_success_empty/trait_multi_module_test/src/module2.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module2.nr new file mode 100644 index 00000000000..3db88f40ef7 --- /dev/null +++ b/test_programs/compile_success_empty/trait_multi_module_test/src/module2.nr @@ -0,0 +1 @@ +pub struct MyStruct {} diff --git a/test_programs/compile_success_empty/trait_multi_module_test/src/module3.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module3.nr new file mode 100644 index 00000000000..2485a2ba7a1 --- /dev/null +++ b/test_programs/compile_success_empty/trait_multi_module_test/src/module3.nr @@ -0,0 +1,4 @@ +use crate::module1::MyTrait; +use crate::module2::MyStruct; +// ensure we can implement traits that are imported with the `use` syntax +impl MyTrait for MyStruct {} diff --git a/test_programs/compile_success_empty/trait_multi_module_test/src/module4.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module4.nr new file mode 100644 index 00000000000..487cc404726 --- /dev/null +++ b/test_programs/compile_success_empty/trait_multi_module_test/src/module4.nr @@ -0,0 +1 @@ +pub trait MyTrait4 {} diff --git a/test_programs/compile_success_empty/trait_multi_module_test/src/module5.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module5.nr new file mode 100644 index 00000000000..9c58cf799db --- /dev/null +++ b/test_programs/compile_success_empty/trait_multi_module_test/src/module5.nr @@ -0,0 +1 @@ +pub struct MyStruct5 {} diff --git a/test_programs/compile_success_empty/trait_multi_module_test/src/module6.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module6.nr new file mode 100644 index 00000000000..cb4eb3a2956 --- /dev/null +++ b/test_programs/compile_success_empty/trait_multi_module_test/src/module6.nr @@ -0,0 +1,2 @@ +// ensure we can implement traits using the Path syntax +impl crate::module4::MyTrait4 for crate::module5::MyStruct5 {} diff --git a/test_programs/compile_success_empty/trait_override_implementation/Nargo.toml b/test_programs/compile_success_empty/trait_override_implementation/Nargo.toml new file mode 100644 index 00000000000..1ccf15adc14 --- /dev/null +++ b/test_programs/compile_success_empty/trait_override_implementation/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_override_implementation" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/trait_override_implementation/src/main.nr b/test_programs/compile_success_empty/trait_override_implementation/src/main.nr new file mode 100644 index 00000000000..12a625b0843 --- /dev/null +++ b/test_programs/compile_success_empty/trait_override_implementation/src/main.nr @@ -0,0 +1,83 @@ +trait MyDefault { + fn my_default(x: Field, y: Field) -> Self; + + fn method2(x: Field) -> Field { + x + } +} + +struct Foo { + bar: Field, + array: [Field; 2], +} + +impl MyDefault for Foo { + fn my_default(x: Field, y: Field) -> Self { + Self { bar: x, array: [x, y] } + } + + fn method2(x: Field) -> Field { + x * 3 + } +} + +trait F { + fn f1(self) -> Field; + fn f2(_self: Self) -> Field { + 2 + } + fn f3(_self: Self) -> Field { + 3 + } + fn f4(_self: Self) -> Field { + 4 + } + fn f5(_self: Self) -> Field { + 5 + } +} + +struct Bar {} + +impl F for Bar { + fn f5(_self: Self) -> Field { + 50 + } + fn f1(_self: Self) -> Field { + 10 + } + fn f3(_self: Self) -> Field { + 30 + } +} +// Impls on mutable references are temporarily disabled +// impl F for &mut Bar { +// fn f1(self) -> Field { 101 } +// fn f5(self) -> Field { 505 } +// } +fn main(x: Field) { + let first = Foo::method2(x); + assert(first == 3 * x); + + let bar = Bar {}; + + assert(bar.f1() == 10, "1"); + assert(bar.f2() == 2, "2"); + assert(bar.f3() == 30, "3"); + assert(bar.f4() == 4, "4"); + assert(bar.f5() == 50, "5"); + + let mut bar_mut = Bar {}; + // Impls on mutable references are temporarily disabled + // assert_eq((&mut bar_mut).f1(), 101); + // assert((&mut bar_mut).f2() == 2, "7"); + // assert((&mut bar_mut).f3() == 3, "8"); + // assert((&mut bar_mut).f4() == 4, "9"); + // assert((&mut bar_mut).f5() == 505, "10"); + assert(bar_mut.f1() == 10, "10"); + assert(bar_mut.f2() == 2, "12"); + assert(bar_mut.f3() == 30, "13"); + assert(bar_mut.f4() == 4, "14"); + assert(bar_mut.f5() == 50, "15"); +} + diff --git a/test_programs/compile_success_empty/trait_static_methods/Nargo.toml b/test_programs/compile_success_empty/trait_static_methods/Nargo.toml new file mode 100644 index 00000000000..ea30031b9a5 --- /dev/null +++ b/test_programs/compile_success_empty/trait_static_methods/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_static_methods" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/trait_static_methods/src/main.nr b/test_programs/compile_success_empty/trait_static_methods/src/main.nr new file mode 100644 index 00000000000..571f917ab89 --- /dev/null +++ b/test_programs/compile_success_empty/trait_static_methods/src/main.nr @@ -0,0 +1,64 @@ +trait ATrait { + fn asd() -> Self; + + fn static_method() -> Field { + Self::static_method_2() + } + + fn static_method_2() -> Field { + 100 + } +} + +struct Foo { + x: Field, +} +impl ATrait for Foo { + fn asd() -> Self { + // This should pass as Self should be bound to Foo while typechecking this + Foo { x: 100 } + } +} + +struct Bar { + x: Field, +} +impl ATrait for Bar { + // The trait method is declared as returning `Self` + // but explicitly specifying the type in the impl should work + fn asd() -> Bar { + Bar { x: 100 } + } + + fn static_method_2() -> Field { + 200 + } +} + +fn main() { + assert(Foo::static_method() == 100); + assert(Bar::static_method() == 200); + + // Regression for #3773 + let zero: Field = MyDefault::my_default(); + assert(zero == 0); +} + +trait MyDefault { + fn my_default() -> Self; +} + +// This impl is first, so if the type directed search picks the first impl +// instead of the correct Field impl below, we'll get a panic in SSA from +// a type mismatch. +impl MyDefault for (Field, Field) { + fn my_default() -> (Field, Field) { + (0, 0) + } +} + +impl MyDefault for Field { + fn my_default() -> Field { + 0 + } +} diff --git a/test_programs/compile_success_empty/trait_where_clause/Nargo.toml b/test_programs/compile_success_empty/trait_where_clause/Nargo.toml new file mode 100644 index 00000000000..1bbde8bfd79 --- /dev/null +++ b/test_programs/compile_success_empty/trait_where_clause/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_where_clause" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/trait_where_clause/src/main.nr b/test_programs/compile_success_empty/trait_where_clause/src/main.nr new file mode 100644 index 00000000000..8dc00be622d --- /dev/null +++ b/test_programs/compile_success_empty/trait_where_clause/src/main.nr @@ -0,0 +1,86 @@ +// TODO(#2568): Currently we only support trait constraints in a few cases. +// There's a bunch of other places where they can pop up: +// - trait methods (trait Foo where T: ... { ) +// - structs (struct Foo where T: ...) +// import the traits from another module to ensure the where clauses are ok with that +mod the_trait; +use crate::the_trait::Asd; +use crate::the_trait::StaticTrait; + +struct Add10 { + x: Field, +} +struct Add20 { + x: Field, +} +struct Add30 { + x: Field, +} +struct AddXY { + x: Field, + y: Field, +} + +impl Asd for Add10 { + fn asd(self) -> Field { + self.x + 10 + } +} +impl Asd for Add20 { + fn asd(self) -> Field { + self.x + 20 + } +} +impl Asd for Add30 { + fn asd(self) -> Field { + self.x + 30 + } +} + +impl Asd for AddXY { + fn asd(self) -> Field { + self.x + self.y + } +} + +struct Static100 {} +impl StaticTrait for Static100 { + // use default implementation for static_function, which returns 100 +} + +struct Static200 {} +impl StaticTrait for Static200 { + fn static_function(slf: Self) -> Field { + let _ = slf; + 200 + } +} + +fn assert_asd_eq_100(t: T) +where + T: crate::the_trait::Asd, +{ + assert(t.asd() == 100); +} + +fn add_one_to_static_function(t: T) -> Field +where + T: StaticTrait, +{ + T::static_function(t) + 1 +} + +fn main() { + let x = Add10 { x: 90 }; + let z = Add20 { x: 80 }; + let a = Add30 { x: 70 }; + let xy = AddXY { x: 30, y: 70 }; + + assert_asd_eq_100(x); + assert_asd_eq_100(z); + assert_asd_eq_100(a); + assert_asd_eq_100(xy); + + assert(add_one_to_static_function(Static100 {}) == 101); + assert(add_one_to_static_function(Static200 {}) == 201); +} diff --git a/test_programs/compile_success_empty/trait_where_clause/src/the_trait.nr b/test_programs/compile_success_empty/trait_where_clause/src/the_trait.nr new file mode 100644 index 00000000000..6390856731e --- /dev/null +++ b/test_programs/compile_success_empty/trait_where_clause/src/the_trait.nr @@ -0,0 +1,10 @@ +pub trait Asd { + fn asd(self) -> Field; +} + +pub trait StaticTrait { + fn static_function(slf: Self) -> Field { + let _ = slf; + 100 + } +} diff --git a/test_programs/compile_success_empty/traits/Nargo.toml b/test_programs/compile_success_empty/traits/Nargo.toml new file mode 100644 index 00000000000..a33e8681807 --- /dev/null +++ b/test_programs/compile_success_empty/traits/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "traits" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/traits/src/main.nr b/test_programs/compile_success_empty/traits/src/main.nr new file mode 100644 index 00000000000..9ef0ec6aba9 --- /dev/null +++ b/test_programs/compile_success_empty/traits/src/main.nr @@ -0,0 +1,19 @@ +trait MyDefault { + fn my_default(x: Field, y: Field) -> Self; +} + +struct Foo { + bar: Field, + array: [Field; 2], +} + +impl MyDefault for Foo { + fn my_default(x: Field, y: Field) -> Self { + Self { bar: x, array: [x, y] } + } +} + +fn main(x: Field, y: Field) { + let first = Foo::my_default(x, y); + assert(first.bar == x); +} diff --git a/test_programs/compile_success_empty/turbofish_call_func_diff_types/Nargo.toml b/test_programs/compile_success_empty/turbofish_call_func_diff_types/Nargo.toml new file mode 100644 index 00000000000..8624cda646b --- /dev/null +++ b/test_programs/compile_success_empty/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/compile_success_empty/turbofish_call_func_diff_types/src/main.nr b/test_programs/compile_success_empty/turbofish_call_func_diff_types/src/main.nr new file mode 100644 index 00000000000..e44df34a193 --- /dev/null +++ b/test_programs/compile_success_empty/turbofish_call_func_diff_types/src/main.nr @@ -0,0 +1,37 @@ +use std::hash::Hasher; +use std::hash::poseidon::PoseidonHasher; +use std::hash::poseidon2::Poseidon2Hasher; + +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/compile_success_empty/type_path/Nargo.toml b/test_programs/compile_success_empty/type_path/Nargo.toml new file mode 100644 index 00000000000..0e76437d15f --- /dev/null +++ b/test_programs/compile_success_empty/type_path/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "type_path" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/type_path/src/main.nr b/test_programs/compile_success_empty/type_path/src/main.nr new file mode 100644 index 00000000000..ca9a9008f6c --- /dev/null +++ b/test_programs/compile_success_empty/type_path/src/main.nr @@ -0,0 +1,19 @@ +fn main() { + comptime { + let foo = quote { Foo }.as_type(); + quote { + $foo::static() + } + } + + // Make sure this call works fine: in the past we used to not distinguish + // whether a TypePath had generics or not, always resolved them, filling them + // up with Type::Error, and eventually leading to an ICE. + let _ = Field::from_be_bytes([1]); +} + +pub struct Foo {} + +impl Foo { + fn static() {} +} diff --git a/test_programs/compile_success_empty/unary_operators/Nargo.toml b/test_programs/compile_success_empty/unary_operators/Nargo.toml new file mode 100644 index 00000000000..8ab6f708b8a --- /dev/null +++ b/test_programs/compile_success_empty/unary_operators/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "unary_operators" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/unary_operators/src/main.nr b/test_programs/compile_success_empty/unary_operators/src/main.nr new file mode 100644 index 00000000000..8793086c1c1 --- /dev/null +++ b/test_programs/compile_success_empty/unary_operators/src/main.nr @@ -0,0 +1,7 @@ +fn main() { + let x = -1; + assert(x == 1 - 2); + + let y: i32 = -1; + assert(y == 1 - 2); +} diff --git a/test_programs/compile_success_empty/unit/Nargo.toml b/test_programs/compile_success_empty/unit/Nargo.toml new file mode 100644 index 00000000000..7a15bd803c0 --- /dev/null +++ b/test_programs/compile_success_empty/unit/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "unit" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/unit/src/main.nr b/test_programs/compile_success_empty/unit/src/main.nr new file mode 100644 index 00000000000..603829ec6db --- /dev/null +++ b/test_programs/compile_success_empty/unit/src/main.nr @@ -0,0 +1,18 @@ +fn main() { + let _a = (); + let _b: () = _a; + let _c: () = (); + let _d = f1(); + let _e: () = f2(); + let _f: () = f3(); + let _g = f4(); +} + +fn f1() {} +fn f2() { + () +} +fn f3() -> () {} +fn f4() -> () { + () +} diff --git a/test_programs/compile_success_empty/unit_value/Nargo.toml b/test_programs/compile_success_empty/unit_value/Nargo.toml new file mode 100644 index 00000000000..1f9c4524ec5 --- /dev/null +++ b/test_programs/compile_success_empty/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/compile_success_empty/unit_value/src/main.nr b/test_programs/compile_success_empty/unit_value/src/main.nr new file mode 100644 index 00000000000..18c7e5f4f7d --- /dev/null +++ b/test_programs/compile_success_empty/unit_value/src/main.nr @@ -0,0 +1,7 @@ +fn get_transaction() { + std::mem::zeroed() +} + +fn main() { + get_transaction(); +} diff --git a/test_programs/compile_success_empty/unquote/Nargo.toml b/test_programs/compile_success_empty/unquote/Nargo.toml new file mode 100644 index 00000000000..68b2890e37a --- /dev/null +++ b/test_programs/compile_success_empty/unquote/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unquote" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/unquote/src/main.nr b/test_programs/compile_success_empty/unquote/src/main.nr new file mode 100644 index 00000000000..2717286b810 --- /dev/null +++ b/test_programs/compile_success_empty/unquote/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + std::meta::unquote!(quote { assert(true); }); + assert(std::meta::unquote!(quote { true })); +} diff --git a/test_programs/compile_success_empty/unquote_function/Nargo.toml b/test_programs/compile_success_empty/unquote_function/Nargo.toml new file mode 100644 index 00000000000..aa56a5798df --- /dev/null +++ b/test_programs/compile_success_empty/unquote_function/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unquote_function" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/unquote_function/src/main.nr b/test_programs/compile_success_empty/unquote_function/src/main.nr new file mode 100644 index 00000000000..7b6442abe8a --- /dev/null +++ b/test_programs/compile_success_empty/unquote_function/src/main.nr @@ -0,0 +1,12 @@ +fn main() { + bar(); +} + +#[output_function] +pub fn foo() {} + +comptime fn output_function(_f: FunctionDefinition) -> Quoted { + quote { + fn bar() {} + } +} diff --git a/test_programs/compile_success_empty/unquote_multiple_items_from_annotation/Nargo.toml b/test_programs/compile_success_empty/unquote_multiple_items_from_annotation/Nargo.toml new file mode 100644 index 00000000000..63f15f2b349 --- /dev/null +++ b/test_programs/compile_success_empty/unquote_multiple_items_from_annotation/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unquote_multiple_items_from_annotation" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/unquote_multiple_items_from_annotation/src/main.nr b/test_programs/compile_success_empty/unquote_multiple_items_from_annotation/src/main.nr new file mode 100644 index 00000000000..591c03de905 --- /dev/null +++ b/test_programs/compile_success_empty/unquote_multiple_items_from_annotation/src/main.nr @@ -0,0 +1,14 @@ +#[foo] +pub struct Foo {} + +fn main() { + assert_eq(ONE, 1); + assert_eq(TWO, 2); +} + +comptime fn foo(_: StructDefinition) -> Quoted { + quote { + global ONE: Field = 1; + global TWO: u32 = 2; + } +} diff --git a/test_programs/compile_success_empty/unquote_struct/Nargo.toml b/test_programs/compile_success_empty/unquote_struct/Nargo.toml new file mode 100644 index 00000000000..c40d6a07093 --- /dev/null +++ b/test_programs/compile_success_empty/unquote_struct/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unquote_struct" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/unquote_struct/src/main.nr b/test_programs/compile_success_empty/unquote_struct/src/main.nr new file mode 100644 index 00000000000..d4ab275858c --- /dev/null +++ b/test_programs/compile_success_empty/unquote_struct/src/main.nr @@ -0,0 +1,30 @@ +fn main() { + let foo = Foo { x: 4, y: 4 }; + foo.assert_equal(); +} + +#[output_struct] +fn foo(x: Field, y: u32) -> u32 { + x as u32 + y +} + +// Given a function, wrap its parameters in a struct definition +comptime fn output_struct(f: FunctionDefinition) -> Quoted { + let fields = f + .parameters() + .map(|param: (Quoted, Type)| { + let name = param.0; + let typ = param.1; + quote { $name: $typ, } + }) + .join(quote {}); + + quote { + struct Foo { $fields } + impl Foo { + fn assert_equal(self) { + assert_eq(self.x as u32, self.y); + } + } + } +} diff --git a/test_programs/compile_success_empty/unused_variables/Nargo.toml b/test_programs/compile_success_empty/unused_variables/Nargo.toml new file mode 100644 index 00000000000..1447f07d81d --- /dev/null +++ b/test_programs/compile_success_empty/unused_variables/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "unused_variables" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/unused_variables/src/main.nr b/test_programs/compile_success_empty/unused_variables/src/main.nr new file mode 100644 index 00000000000..2fb57e3b275 --- /dev/null +++ b/test_programs/compile_success_empty/unused_variables/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: Field, y: pub Field) { + let _ = x; + let _ = y; +} diff --git a/test_programs/compile_success_empty/use_callers_scope/Nargo.toml b/test_programs/compile_success_empty/use_callers_scope/Nargo.toml new file mode 100644 index 00000000000..14402c7d7b1 --- /dev/null +++ b/test_programs/compile_success_empty/use_callers_scope/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "use_callers_scope" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/use_callers_scope/src/main.nr b/test_programs/compile_success_empty/use_callers_scope/src/main.nr new file mode 100644 index 00000000000..26429997f0e --- /dev/null +++ b/test_programs/compile_success_empty/use_callers_scope/src/main.nr @@ -0,0 +1,30 @@ +#[bar::struct_attr] +pub struct Foo {} + +pub struct Bar {} + +#[bar::fn_attr] +fn main() {} + +mod bar { + #[use_callers_scope] + pub comptime fn struct_attr(_: StructDefinition) { + let _ = quote { Bar }.as_type(); + } + + #[use_callers_scope] + pub comptime fn fn_attr(_: FunctionDefinition) { + let _ = quote { Bar }.as_type(); + let _ = nested(); + + // Ensure closures can still access Bar even + // though `map` separates them from `fn_attr`. + let _ = &[1, 2, 3].map(|_| quote { Bar }.as_type()); + } + + // use_callers_scope should also work nested + #[use_callers_scope] + comptime fn nested() -> Type { + quote { Bar }.as_type() + } +} diff --git a/test_programs/compile_success_empty/vectors/Nargo.toml b/test_programs/compile_success_empty/vectors/Nargo.toml new file mode 100644 index 00000000000..e4c3889c685 --- /dev/null +++ b/test_programs/compile_success_empty/vectors/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "vectors" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/vectors/src/main.nr b/test_programs/compile_success_empty/vectors/src/main.nr new file mode 100644 index 00000000000..ac02a4691dd --- /dev/null +++ b/test_programs/compile_success_empty/vectors/src/main.nr @@ -0,0 +1,32 @@ +use std::collections::vec::Vec; + +fn main(x: Field, y: pub Field) { + let mut vector = Vec::new(); + + assert(vector.len() == 0); + for i in 0..5 { + vector.push(i); + } + assert(vector.len() == 5); + for i in 0..5 { + assert(i == vector.get(i)); + } + + let last_elem = vector.pop(); + assert(last_elem == 4); + assert(vector.len() == 4); + + vector.insert(2, 100); + assert(vector.get(2) == 100); + assert(vector.get(4) == 3); + assert(vector.len() == 5); + + let removed_elem = vector.remove(3); + assert(removed_elem == 2); + assert(vector.get(3) == 3); + assert(vector.len() == 4); + + 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_success_empty/workspace_reexport_bug/Nargo.toml b/test_programs/compile_success_empty/workspace_reexport_bug/Nargo.toml new file mode 100644 index 00000000000..ea2ffc0d2eb --- /dev/null +++ b/test_programs/compile_success_empty/workspace_reexport_bug/Nargo.toml @@ -0,0 +1,7 @@ +[workspace] +members = [ + "library", + "library2", + "binary" +] +default-member = "binary" \ No newline at end of file diff --git a/test_programs/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml b/test_programs/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml new file mode 100644 index 00000000000..90d8321589b --- /dev/null +++ b/test_programs/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "binary" +type = "bin" +authors = [""] +[dependencies] +library = { path = "../library" } \ No newline at end of file diff --git a/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr b/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr new file mode 100644 index 00000000000..a4207794a8a --- /dev/null +++ b/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr @@ -0,0 +1,2 @@ +use library::ReExportMeFromAnotherLib; +fn main(_x: ReExportMeFromAnotherLib) {} diff --git a/test_programs/compile_success_empty/workspace_reexport_bug/library/Nargo.toml b/test_programs/compile_success_empty/workspace_reexport_bug/library/Nargo.toml new file mode 100644 index 00000000000..88831bada4e --- /dev/null +++ b/test_programs/compile_success_empty/workspace_reexport_bug/library/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "library" +type = "lib" +authors = [""] + +[dependencies] +library2 = { path = "../library2"} \ No newline at end of file diff --git a/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr b/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr new file mode 100644 index 00000000000..e56c127f562 --- /dev/null +++ b/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr @@ -0,0 +1,2 @@ +// Re-export +pub use library2::ReExportMeFromAnotherLib; diff --git a/test_programs/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml b/test_programs/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml new file mode 100644 index 00000000000..f2c20c0bf4a --- /dev/null +++ b/test_programs/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "library" +type = "lib" +authors = [""] +[dependencies] diff --git a/test_programs/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr b/test_programs/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr new file mode 100644 index 00000000000..c38c7bd1675 --- /dev/null +++ b/test_programs/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr @@ -0,0 +1,5 @@ +// When we re-export this type from another library and then use it in +// main, we get a panic +pub struct ReExportMeFromAnotherLib { + x : Field, +} diff --git a/test_programs/compile_success_empty/zeroed_slice/Nargo.toml b/test_programs/compile_success_empty/zeroed_slice/Nargo.toml new file mode 100644 index 00000000000..650baead9e2 --- /dev/null +++ b/test_programs/compile_success_empty/zeroed_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "zeroed_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/zeroed_slice/src/main.nr b/test_programs/compile_success_empty/zeroed_slice/src/main.nr new file mode 100644 index 00000000000..b35afdbc6c6 --- /dev/null +++ b/test_programs/compile_success_empty/zeroed_slice/src/main.nr @@ -0,0 +1,3 @@ +fn main() { + let _: [u8] = std::mem::zeroed(); +} diff --git a/test_programs/compile_success_no_bug/check_unconstrained_regression/Nargo.toml b/test_programs/compile_success_no_bug/check_unconstrained_regression/Nargo.toml new file mode 100644 index 00000000000..3c6b5d9688c --- /dev/null +++ b/test_programs/compile_success_no_bug/check_unconstrained_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "check_unconstrained_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_no_bug/check_unconstrained_regression/src/main.nr b/test_programs/compile_success_no_bug/check_unconstrained_regression/src/main.nr new file mode 100644 index 00000000000..174b68fd162 --- /dev/null +++ b/test_programs/compile_success_no_bug/check_unconstrained_regression/src/main.nr @@ -0,0 +1,32 @@ +struct Trigger { + x: u32, + y: Field, + z: [Field; 3], +} +struct ResultType { + a: u32, + b: Field, + c: [Field; 3], +} + +unconstrained fn convert(trigger: Trigger) -> ResultType { + let result = ResultType { + a: trigger.x + 1, + b: trigger.y - 1 + trigger.z[2], + c: [trigger.z[0], 0, trigger.z[1]], + }; + result +} +impl Trigger { + fn execute(self) -> ResultType { + /// Safety: testing context + let result = unsafe { convert(self) }; + assert(result.a == self.x + 1); + assert(result.b == self.y - 1 + self.z[2]); + assert(result.c[1] == 0); + result + } +} +fn main(x: Trigger) -> pub ResultType { + x.execute() +} diff --git a/test_programs/compile_success_no_bug/databus_mapping_regression/Nargo.toml b/test_programs/compile_success_no_bug/databus_mapping_regression/Nargo.toml new file mode 100644 index 00000000000..7ce13902c32 --- /dev/null +++ b/test_programs/compile_success_no_bug/databus_mapping_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "databus_mapping_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/compile_success_no_bug/databus_mapping_regression/src/main.nr b/test_programs/compile_success_no_bug/databus_mapping_regression/src/main.nr new file mode 100644 index 00000000000..9b6ad264a9e --- /dev/null +++ b/test_programs/compile_success_no_bug/databus_mapping_regression/src/main.nr @@ -0,0 +1,42 @@ +trait Empty { + fn empty() -> Self; +} + +impl Empty for Field { + fn empty() -> Self { + 0 + } +} + +pub fn is_empty(item: T) -> bool where T: Empty + Eq { + item.eq(T::empty()) +} + +pub fn array_to_bounded_vec(array: [T; N]) -> BoundedVec where T: Empty + Eq { + let mut len = 0; + for elem in array { + if !is_empty(elem) { + len += 1; + } + } + + BoundedVec { storage: array, len } +} + +global TX_SIZE: u32 = 5; +global APP_CALL_SIZE: u32 = 2; + +fn main( + a: call_data(0) [Field; TX_SIZE], + b: call_data(1) [Field; APP_CALL_SIZE] +) -> return_data [Field; TX_SIZE] { + let mut a_as_bounded_vec = array_to_bounded_vec(a); + + for i in 0..APP_CALL_SIZE { + let value = b[i]; + if value != 0 { + a_as_bounded_vec.push(value); + } + } + a_as_bounded_vec.storage() +} diff --git a/test_programs/compile_success_with_bug/underconstrained_value_detector_5425/Nargo.toml b/test_programs/compile_success_with_bug/underconstrained_value_detector_5425/Nargo.toml new file mode 100644 index 00000000000..48ab5a0390b --- /dev/null +++ b/test_programs/compile_success_with_bug/underconstrained_value_detector_5425/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "underconstrained_value_detector_5425" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_with_bug/underconstrained_value_detector_5425/src/main.nr b/test_programs/compile_success_with_bug/underconstrained_value_detector_5425/src/main.nr new file mode 100644 index 00000000000..22e2bc0b49d --- /dev/null +++ b/test_programs/compile_success_with_bug/underconstrained_value_detector_5425/src/main.nr @@ -0,0 +1,49 @@ +unconstrained fn maximum_price(options: [u32; 3]) -> u32 { + let mut maximum_option = 0; + for option in options { + if (option > maximum_option) { + maximum_option = option; + } + } + maximum_option +} + +fn main(sandwiches: pub [u32; 3], drinks: pub [u32; 3], snacks: pub [u32; 3], best_value: u32) { + /// Safety: testing context + unsafe { + let meal_deal_cost: u32 = 390; + let most_expensive_sandwich = maximum_price(sandwiches); + let mut sandwich_exists = false; + for sandwich_price in sandwiches { + assert(sandwich_price <= most_expensive_sandwich); + sandwich_exists |= sandwich_price == most_expensive_sandwich; + } + + // maximum_price(sandwiches) is properly constrained with this assert, + // linking the result to the arguments + assert(sandwich_exists); + + let most_expensive_drink = maximum_price(drinks); + let mut drink_exists = false; + for drink_price in drinks { + assert(drink_price <= most_expensive_drink); + drink_exists |= drink_price == most_expensive_drink; + } + + // maximum_price(drinks) is properly constrained with this assert, + // linking the result to the arguments + assert(drink_exists); + + let most_expensive_snack = maximum_price(snacks); + // maximum_price(snacks)'s result isn't constrained against `snacks` + // in any way, triggering the missing Brillig constraint check + + assert( + best_value + == ( + most_expensive_sandwich + most_expensive_drink + most_expensive_snack + - meal_deal_cost + ), + ); + } +} diff --git a/test_programs/execution_failure/assert_msg_runtime/Nargo.toml b/test_programs/execution_failure/assert_msg_runtime/Nargo.toml new file mode 100644 index 00000000000..765f632ff74 --- /dev/null +++ b/test_programs/execution_failure/assert_msg_runtime/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_msg_runtime" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/assert_msg_runtime/Prover.toml b/test_programs/execution_failure/assert_msg_runtime/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_failure/assert_msg_runtime/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_failure/assert_msg_runtime/src/main.nr b/test_programs/execution_failure/assert_msg_runtime/src/main.nr new file mode 100644 index 00000000000..fa21442e816 --- /dev/null +++ b/test_programs/execution_failure/assert_msg_runtime/src/main.nr @@ -0,0 +1,7 @@ +fn main(x: Field, y: pub Field) { + assert(x != y, f"Expected x != y, but got both equal {x}"); + assert(x != y); + 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}"); +} diff --git a/test_programs/execution_failure/bigint_from_too_many_le_bytes/Nargo.toml b/test_programs/execution_failure/bigint_from_too_many_le_bytes/Nargo.toml new file mode 100644 index 00000000000..cbdfc2d83d9 --- /dev/null +++ b/test_programs/execution_failure/bigint_from_too_many_le_bytes/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bigint_from_too_many_le_bytes" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/bigint_from_too_many_le_bytes/src/main.nr b/test_programs/execution_failure/bigint_from_too_many_le_bytes/src/main.nr new file mode 100644 index 00000000000..2d4587ee3d9 --- /dev/null +++ b/test_programs/execution_failure/bigint_from_too_many_le_bytes/src/main.nr @@ -0,0 +1,22 @@ +use std::bigint::{bn254_fq, BigInt}; + +// TODO(https://github.com/noir-lang/noir/issues/5580): decide whether this is desired behavior +// +// Fails at execution time: +// +// error: Assertion failed: 'Index out of bounds' +// ┌─ std/cmp.nr:35:34 +// │ +// 35 │ result &= self[i].eq(other[i]); +// │ -------- +// │ +// = Call stack: +// 1. /Users/michaelklein/Coding/rust/noir/test_programs/compile_failure/bigint_from_too_many_le_bytes/src/main.nr:7:12 +// 2. std/cmp.nr:35:34 +// Failed assertion +fn main() { + let bytes: [u8] = bn254_fq.push_front(0x00); + let bigint = BigInt::from_le_bytes(bytes, bn254_fq); + let result_bytes = bigint.to_le_bytes(); + assert(bytes == result_bytes.as_slice()); +} diff --git a/test_programs/execution_failure/brillig_assert_fail/Nargo.toml b/test_programs/execution_failure/brillig_assert_fail/Nargo.toml new file mode 100644 index 00000000000..7ce776e5ce6 --- /dev/null +++ b/test_programs/execution_failure/brillig_assert_fail/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_assert_fail" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_failure/brillig_assert_fail/Prover.toml b/test_programs/execution_failure/brillig_assert_fail/Prover.toml new file mode 100644 index 00000000000..11497a473bc --- /dev/null +++ b/test_programs/execution_failure/brillig_assert_fail/Prover.toml @@ -0,0 +1 @@ +x = "0" diff --git a/test_programs/execution_failure/brillig_assert_fail/src/main.nr b/test_programs/execution_failure/brillig_assert_fail/src/main.nr new file mode 100644 index 00000000000..18e6422361c --- /dev/null +++ b/test_programs/execution_failure/brillig_assert_fail/src/main.nr @@ -0,0 +1,12 @@ +// Tests a very simple program. +// +// The features being tested is using assert on brillig +fn main(x: Field) { + /// Safety: testing context + assert(1 == unsafe { conditional(x as bool) }); +} + +unconstrained fn conditional(x: bool) -> Field { + assert(x); + 1 +} diff --git a/test_programs/execution_failure/brillig_assert_msg_runtime/Nargo.toml b/test_programs/execution_failure/brillig_assert_msg_runtime/Nargo.toml new file mode 100644 index 00000000000..00f97b7273a --- /dev/null +++ b/test_programs/execution_failure/brillig_assert_msg_runtime/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_assert_msg_runtime" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/brillig_assert_msg_runtime/Prover.toml b/test_programs/execution_failure/brillig_assert_msg_runtime/Prover.toml new file mode 100644 index 00000000000..0e5dfd5638d --- /dev/null +++ b/test_programs/execution_failure/brillig_assert_msg_runtime/Prover.toml @@ -0,0 +1 @@ +x = "5" diff --git a/test_programs/execution_failure/brillig_assert_msg_runtime/src/main.nr b/test_programs/execution_failure/brillig_assert_msg_runtime/src/main.nr new file mode 100644 index 00000000000..9c07660217b --- /dev/null +++ b/test_programs/execution_failure/brillig_assert_msg_runtime/src/main.nr @@ -0,0 +1,11 @@ +fn main(x: Field) { + /// Safety: testing context + assert(1 == unsafe { conditional(x) }); +} + +unconstrained fn conditional(x: Field) -> Field { + let z = x as u8 + 20; + assert_eq(z, 25, f"Expected 25 but got {z}"); + assert(x == 10, f"Expected x to equal 10, but got {x}"); + 1 +} diff --git a/test_programs/execution_failure/div_by_zero_constants/Nargo.toml b/test_programs/execution_failure/div_by_zero_constants/Nargo.toml new file mode 100644 index 00000000000..aad13c7d97f --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_constants/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "divide_by_zero" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/div_by_zero_constants/Prover.toml b/test_programs/execution_failure/div_by_zero_constants/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/execution_failure/div_by_zero_constants/src/main.nr b/test_programs/execution_failure/div_by_zero_constants/src/main.nr new file mode 100644 index 00000000000..f90b3ef9429 --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_constants/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + let a: Field = 3 / 0; + std::println(a); +} diff --git a/test_programs/execution_failure/div_by_zero_modulo/Nargo.toml b/test_programs/execution_failure/div_by_zero_modulo/Nargo.toml new file mode 100644 index 00000000000..22ff18075cd --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_modulo/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "div_by_zero_modulo" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/div_by_zero_modulo/Prover.toml b/test_programs/execution_failure/div_by_zero_modulo/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/execution_failure/div_by_zero_modulo/src/main.nr b/test_programs/execution_failure/div_by_zero_modulo/src/main.nr new file mode 100644 index 00000000000..d938ab7fca8 --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_modulo/src/main.nr @@ -0,0 +1,7 @@ +fn main() { + let a: u32 = 6; + let b = 3; + let c = 0; + let res = (a * b) % c; + assert(res != 5); +} diff --git a/test_programs/execution_failure/div_by_zero_numerator_witness/Nargo.toml b/test_programs/execution_failure/div_by_zero_numerator_witness/Nargo.toml new file mode 100644 index 00000000000..30a7eb62645 --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_numerator_witness/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "div_by_zero_numerator_witness" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/div_by_zero_numerator_witness/Prover.toml b/test_programs/execution_failure/div_by_zero_numerator_witness/Prover.toml new file mode 100644 index 00000000000..07890234a19 --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_numerator_witness/Prover.toml @@ -0,0 +1 @@ +x = "3" diff --git a/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr b/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr new file mode 100644 index 00000000000..012e823b297 --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: Field) { + let a: Field = x / 0; + std::println(a); +} diff --git a/test_programs/execution_failure/div_by_zero_witness/Nargo.toml b/test_programs/execution_failure/div_by_zero_witness/Nargo.toml new file mode 100644 index 00000000000..e4968f6182d --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_witness/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "div_by_zero_witness" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/div_by_zero_witness/Prover.toml b/test_programs/execution_failure/div_by_zero_witness/Prover.toml new file mode 100644 index 00000000000..a1f166bf325 --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_witness/Prover.toml @@ -0,0 +1,2 @@ +x = "3" +y = "0" diff --git a/test_programs/execution_failure/div_by_zero_witness/src/main.nr b/test_programs/execution_failure/div_by_zero_witness/src/main.nr new file mode 100644 index 00000000000..eaa3c1f2a72 --- /dev/null +++ b/test_programs/execution_failure/div_by_zero_witness/src/main.nr @@ -0,0 +1,5 @@ +// It is expected that `y` must be equal to 0. +fn main(x: Field, y: pub Field) { + let a: Field = x / y; + std::println(a); +} diff --git a/test_programs/execution_failure/dyn_index_fail_nested_array/Nargo.toml b/test_programs/execution_failure/dyn_index_fail_nested_array/Nargo.toml new file mode 100644 index 00000000000..7f1c2c097a4 --- /dev/null +++ b/test_programs/execution_failure/dyn_index_fail_nested_array/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "dyn_index_fail_nested_array" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/dyn_index_fail_nested_array/Prover.toml b/test_programs/execution_failure/dyn_index_fail_nested_array/Prover.toml new file mode 100644 index 00000000000..00ffa6e4620 --- /dev/null +++ b/test_programs/execution_failure/dyn_index_fail_nested_array/Prover.toml @@ -0,0 +1,13 @@ +y = "2" + +[[x]] +a = "1" +b = "2" + +[[x]] +a = "3" +b = "4" + +[[x]] +a = "5" +b = "6" diff --git a/test_programs/execution_failure/dyn_index_fail_nested_array/src/main.nr b/test_programs/execution_failure/dyn_index_fail_nested_array/src/main.nr new file mode 100644 index 00000000000..954d2e77c6e --- /dev/null +++ b/test_programs/execution_failure/dyn_index_fail_nested_array/src/main.nr @@ -0,0 +1,8 @@ +struct Foo { + a: Field, + b: Field, +} + +fn main(mut x: [Foo; 3], y: pub Field) { + assert(x[y + 2].a == 5); +} diff --git a/test_programs/execution_failure/dynamic_index_failure/Nargo.toml b/test_programs/execution_failure/dynamic_index_failure/Nargo.toml new file mode 100644 index 00000000000..2c44a5356c3 --- /dev/null +++ b/test_programs/execution_failure/dynamic_index_failure/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "dynamic_index_failure" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/dynamic_index_failure/Prover.toml b/test_programs/execution_failure/dynamic_index_failure/Prover.toml new file mode 100644 index 00000000000..caf3448c56f --- /dev/null +++ b/test_programs/execution_failure/dynamic_index_failure/Prover.toml @@ -0,0 +1,2 @@ +x = [104, 101, 108, 108, 111] +z = "4" diff --git a/test_programs/execution_failure/dynamic_index_failure/src/main.nr b/test_programs/execution_failure/dynamic_index_failure/src/main.nr new file mode 100644 index 00000000000..0af5f90eea6 --- /dev/null +++ b/test_programs/execution_failure/dynamic_index_failure/src/main.nr @@ -0,0 +1,21 @@ +fn main(mut x: [u32; 5], z: Field) { + let idx = z + 10; + + x[z] = 4; + // Dynamic index is greater than length of the array + assert(x[idx] != 0); + // TODO(#2133): Provide more accurate call stacks for arrays merged in if statements + // if z != 20 { + // x[0] = x[4]; + // } else { + // // TODO: Dynamic predicate still gives index out of bounds error + // if idx as u32 < 3 { + // x[idx] = 10; + // } + // x[idx] = 10; + // for i in 0..5 { + // x[idx] = x[i]; + // } + // } + // assert(x[idx] != 0); +} diff --git a/test_programs/execution_failure/empty_composite_array_get/Nargo.toml b/test_programs/execution_failure/empty_composite_array_get/Nargo.toml new file mode 100644 index 00000000000..fa4614c8351 --- /dev/null +++ b/test_programs/execution_failure/empty_composite_array_get/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "empty_composite_array_get" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/empty_composite_array_get/Prover.toml b/test_programs/execution_failure/empty_composite_array_get/Prover.toml new file mode 100644 index 00000000000..ff52a8c5bce --- /dev/null +++ b/test_programs/execution_failure/empty_composite_array_get/Prover.toml @@ -0,0 +1 @@ +empty_input = [] \ No newline at end of file diff --git a/test_programs/execution_failure/empty_composite_array_get/src/main.nr b/test_programs/execution_failure/empty_composite_array_get/src/main.nr new file mode 100644 index 00000000000..1ed9fe4a5e0 --- /dev/null +++ b/test_programs/execution_failure/empty_composite_array_get/src/main.nr @@ -0,0 +1,5 @@ +fn main(empty_input: [(Field, Field); 0]) { + let empty_array: [(Field, Field); 0] = []; + let _ = empty_input[0]; + let _ = empty_array[0]; +} 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..bbb6f8ff422 --- /dev/null +++ b/test_programs/execution_failure/fold_nested_brillig_assert_fail/src/main.nr @@ -0,0 +1,30 @@ +// 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)); + 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 { + /// Safety: testing context + unsafe { + 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/execution_failure/hashmap_load_factor/Nargo.toml b/test_programs/execution_failure/hashmap_load_factor/Nargo.toml new file mode 100644 index 00000000000..92da5a357f4 --- /dev/null +++ b/test_programs/execution_failure/hashmap_load_factor/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "hashmap_load_factor" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file 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/execution_failure/hashmap_load_factor/src/main.nr b/test_programs/execution_failure/hashmap_load_factor/src/main.nr new file mode 100644 index 00000000000..e95da67a084 --- /dev/null +++ b/test_programs/execution_failure/hashmap_load_factor/src/main.nr @@ -0,0 +1,35 @@ +use std::collections::map::HashMap; +use std::hash::BuildHasherDefault; +use std::hash::poseidon2::Poseidon2Hasher; + +struct Entry{ + key: Field, + value: Field +} + +global HASHMAP_CAP = 8; +global HASHMAP_LEN = 6; + +fn allocate_hashmap() -> HashMap> { + HashMap::default() +} + +fn main(input: [Entry; HASHMAP_LEN]) { + test_load_factor(input); +} + +// In this test we exceed load factor: +// α_max = 0.75, thus for capacity of 8 and lenght of 6 +// insertion of new unique key (7-th) should throw assertion error. +fn test_load_factor(input: [Entry; HASHMAP_LEN]) { + let mut hashmap = allocate_hashmap(); + + for entry in input { + hashmap.insert(entry.key, entry.value); + } + + // We use prime numbers for testing, + // therefore it is guaranteed that doubling key we get unique value. + let key = input[0].key * 2; + hashmap.insert(key, input[0].value); +} diff --git a/test_programs/execution_failure/invalid_comptime_bits_decomposition/Nargo.toml b/test_programs/execution_failure/invalid_comptime_bits_decomposition/Nargo.toml new file mode 100644 index 00000000000..c4efe5b4bb4 --- /dev/null +++ b/test_programs/execution_failure/invalid_comptime_bits_decomposition/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "invalid_comptime_bits_decomposition" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/invalid_comptime_bits_decomposition/src/main.nr b/test_programs/execution_failure/invalid_comptime_bits_decomposition/src/main.nr new file mode 100644 index 00000000000..a9ac06c42c6 --- /dev/null +++ b/test_programs/execution_failure/invalid_comptime_bits_decomposition/src/main.nr @@ -0,0 +1,5 @@ +fn main() -> pub [u1; 1] { + let large_number: Field = 2; + + large_number.to_be_bits() +} diff --git a/test_programs/execution_failure/invalid_comptime_bytes_decomposition/Nargo.toml b/test_programs/execution_failure/invalid_comptime_bytes_decomposition/Nargo.toml new file mode 100644 index 00000000000..7ec63576af3 --- /dev/null +++ b/test_programs/execution_failure/invalid_comptime_bytes_decomposition/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "invalid_comptime_bytes_decomposition" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/invalid_comptime_bytes_decomposition/src/main.nr b/test_programs/execution_failure/invalid_comptime_bytes_decomposition/src/main.nr new file mode 100644 index 00000000000..29be8508575 --- /dev/null +++ b/test_programs/execution_failure/invalid_comptime_bytes_decomposition/src/main.nr @@ -0,0 +1,4 @@ +fn main() -> pub [u8; 1] { + let large_number: Field = 256; + large_number.to_be_bytes() +} diff --git a/test_programs/execution_failure/mocks_in_execution/Nargo.toml b/test_programs/execution_failure/mocks_in_execution/Nargo.toml new file mode 100644 index 00000000000..c83da9a3d0c --- /dev/null +++ b/test_programs/execution_failure/mocks_in_execution/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "mocks_in_execution" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/execution_failure/mocks_in_execution/Prover.toml b/test_programs/execution_failure/mocks_in_execution/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/execution_failure/mocks_in_execution/src/main.nr b/test_programs/execution_failure/mocks_in_execution/src/main.nr new file mode 100644 index 00000000000..b43068ab251 --- /dev/null +++ b/test_programs/execution_failure/mocks_in_execution/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + // Trying to use a mock in `nargo execute` should fail. + let mock = unsafe { std::test::OracleMock::mock("foo") }; + assert_eq(mock.id, 0); +} diff --git a/test_programs/execution_failure/option_expect/Nargo.toml b/test_programs/execution_failure/option_expect/Nargo.toml new file mode 100644 index 00000000000..1ee1215ff71 --- /dev/null +++ b/test_programs/execution_failure/option_expect/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "option_expect" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/option_expect/src/main.nr b/test_programs/execution_failure/option_expect/src/main.nr new file mode 100644 index 00000000000..439ce4f386e --- /dev/null +++ b/test_programs/execution_failure/option_expect/src/main.nr @@ -0,0 +1,8 @@ +fn main() { + let inner_value = 3; + let none = Option::none(); + let some = Option::some(inner_value); + + assert(some.expect(f"Should have the value {inner_value}") == 3); + assert(none.expect(f"Should have the value {inner_value}") == 3); +} diff --git a/test_programs/execution_failure/regression_5202/Nargo.toml b/test_programs/execution_failure/regression_5202/Nargo.toml new file mode 100644 index 00000000000..dcdc044836e --- /dev/null +++ b/test_programs/execution_failure/regression_5202/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5202" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] diff --git a/test_programs/execution_failure/regression_5202/src/main.nr b/test_programs/execution_failure/regression_5202/src/main.nr new file mode 100644 index 00000000000..0c3a9693958 --- /dev/null +++ b/test_programs/execution_failure/regression_5202/src/main.nr @@ -0,0 +1,46 @@ +trait ToField { + fn to_field(self) -> Field; +} + +impl ToField for bool { + fn to_field(self) -> Field { + self as Field + } +} + +unconstrained fn get_unconstrained_option() -> Option { + Option::some(13) +} + +unconstrained fn should_i_assert() -> bool { + false +} + +fn get_magical_boolean() -> bool { + /// Safety: testing context + let option = unsafe { get_unconstrained_option() }; + + let pre_assert = option.is_some().to_field(); + + /// Safety: testing context + if unsafe { should_i_assert() } { + // Note that `should_i_assert` is unconstrained, so Noir should not be able to infer + // any behavior from the contents of this block. In this case it is actually false, so the + // assertion below is not even executed (if it did it'd fail since the values are not equal). + assert_eq(option, Option::some(42)); // <- this seems to be the trigger for the bug + } + + // In my testing, the `option` value exhibits weird behavior from this point on, as if it had been mutated + let post_assert = option.is_some().to_field(); + + // The following expression should be true, but I can get it to evaluate to false depending on how I call it + pre_assert == post_assert +} + +fn main() { + let magic = get_magical_boolean(); + + // One of these asserts should fail. Before #5202, they would both pass + assert_eq(magic, true); + assert_eq(magic, false); +} diff --git a/test_programs/execution_failure/slice_access_failure/Nargo.toml b/test_programs/execution_failure/slice_access_failure/Nargo.toml new file mode 100644 index 00000000000..fc159b7efc1 --- /dev/null +++ b/test_programs/execution_failure/slice_access_failure/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "slice_access_failure" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/slice_access_failure/Prover.toml b/test_programs/execution_failure/slice_access_failure/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_failure/slice_access_failure/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_failure/slice_access_failure/src/main.nr b/test_programs/execution_failure/slice_access_failure/src/main.nr new file mode 100644 index 00000000000..6e8b5c7d841 --- /dev/null +++ b/test_programs/execution_failure/slice_access_failure/src/main.nr @@ -0,0 +1,13 @@ +fn main(x: Field, y: pub Field) { + let mut slice = [0; 2]; + if x == y { + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice = slice.push_back(x); + } + // This constraint should fail as the slice length is 3 and the index is 3 + // The right hand side AND case ensures that the circuit inputs have not changed + // and we always hit the else case in the if statement above. + assert((slice[3] == 0) & (slice[2] != y)); +} diff --git a/test_programs/execution_failure/slice_insert_failure/Nargo.toml b/test_programs/execution_failure/slice_insert_failure/Nargo.toml new file mode 100644 index 00000000000..5134032264c --- /dev/null +++ b/test_programs/execution_failure/slice_insert_failure/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "slice_insert_failure" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/slice_insert_failure/Prover.toml b/test_programs/execution_failure/slice_insert_failure/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_failure/slice_insert_failure/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_failure/slice_insert_failure/src/main.nr b/test_programs/execution_failure/slice_insert_failure/src/main.nr new file mode 100644 index 00000000000..38892f01e12 --- /dev/null +++ b/test_programs/execution_failure/slice_insert_failure/src/main.nr @@ -0,0 +1,11 @@ +fn main(x: Field, y: pub Field) { + let mut slice = [0; 2]; + if x == y { + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice = slice.push_back(x); + } + + slice = slice.insert(10, 100); +} diff --git a/test_programs/execution_failure/slice_remove_failure/Nargo.toml b/test_programs/execution_failure/slice_remove_failure/Nargo.toml new file mode 100644 index 00000000000..1e13dfe6483 --- /dev/null +++ b/test_programs/execution_failure/slice_remove_failure/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "slice_remove_failure" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/slice_remove_failure/Prover.toml b/test_programs/execution_failure/slice_remove_failure/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_failure/slice_remove_failure/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_failure/slice_remove_failure/src/main.nr b/test_programs/execution_failure/slice_remove_failure/src/main.nr new file mode 100644 index 00000000000..f9faa25384b --- /dev/null +++ b/test_programs/execution_failure/slice_remove_failure/src/main.nr @@ -0,0 +1,11 @@ +fn main(x: Field, y: pub Field) { + let mut slice = [0; 2]; + if x == y { + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice = slice.push_back(x); + } + + let (removed_slice, removed_elem) = slice.remove(10); +} diff --git a/test_programs/execution_failure/unused_array_get_known_index_out_of_bounds/Nargo.toml b/test_programs/execution_failure/unused_array_get_known_index_out_of_bounds/Nargo.toml new file mode 100644 index 00000000000..4123215e2b6 --- /dev/null +++ b/test_programs/execution_failure/unused_array_get_known_index_out_of_bounds/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unused_array_get_known_index_out_of_bounds" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/unused_array_get_known_index_out_of_bounds/Prover.toml b/test_programs/execution_failure/unused_array_get_known_index_out_of_bounds/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/execution_failure/unused_array_get_known_index_out_of_bounds/src/main.nr b/test_programs/execution_failure/unused_array_get_known_index_out_of_bounds/src/main.nr new file mode 100644 index 00000000000..bdc645ec483 --- /dev/null +++ b/test_programs/execution_failure/unused_array_get_known_index_out_of_bounds/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + let array = [1, 2, 3]; + let _ = array[10]; // Index out of bounds +} diff --git a/test_programs/execution_failure/unused_array_get_unknown_index_out_of_bounds/Nargo.toml b/test_programs/execution_failure/unused_array_get_unknown_index_out_of_bounds/Nargo.toml new file mode 100644 index 00000000000..04d9146b881 --- /dev/null +++ b/test_programs/execution_failure/unused_array_get_unknown_index_out_of_bounds/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unused_array_get_unknown_index_out_of_bounds" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/unused_array_get_unknown_index_out_of_bounds/Prover.toml b/test_programs/execution_failure/unused_array_get_unknown_index_out_of_bounds/Prover.toml new file mode 100644 index 00000000000..1ec81884d61 --- /dev/null +++ b/test_programs/execution_failure/unused_array_get_unknown_index_out_of_bounds/Prover.toml @@ -0,0 +1 @@ +x = "10" \ No newline at end of file diff --git a/test_programs/execution_failure/unused_array_get_unknown_index_out_of_bounds/src/main.nr b/test_programs/execution_failure/unused_array_get_unknown_index_out_of_bounds/src/main.nr new file mode 100644 index 00000000000..15c2d1f1f23 --- /dev/null +++ b/test_programs/execution_failure/unused_array_get_unknown_index_out_of_bounds/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: Field) { + let array = [1, 2, 3]; + let _ = array[x]; // Index out of bounds +} diff --git a/test_programs/execution_failure/unused_array_set_known_index_out_of_bounds/Nargo.toml b/test_programs/execution_failure/unused_array_set_known_index_out_of_bounds/Nargo.toml new file mode 100644 index 00000000000..b8fe7e955a1 --- /dev/null +++ b/test_programs/execution_failure/unused_array_set_known_index_out_of_bounds/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unused_array_set_known_index_out_of_bounds" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/unused_array_set_known_index_out_of_bounds/Prover.toml b/test_programs/execution_failure/unused_array_set_known_index_out_of_bounds/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/execution_failure/unused_array_set_known_index_out_of_bounds/src/main.nr b/test_programs/execution_failure/unused_array_set_known_index_out_of_bounds/src/main.nr new file mode 100644 index 00000000000..9c447aee08f --- /dev/null +++ b/test_programs/execution_failure/unused_array_set_known_index_out_of_bounds/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + let mut array = [1, 2, 3]; + array[10] = 1; // Index out of bounds +} diff --git a/test_programs/execution_failure/unused_array_set_unknown_index_out_of_bounds/Nargo.toml b/test_programs/execution_failure/unused_array_set_unknown_index_out_of_bounds/Nargo.toml new file mode 100644 index 00000000000..ccc00956e80 --- /dev/null +++ b/test_programs/execution_failure/unused_array_set_unknown_index_out_of_bounds/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unused_array_set_unknown_index_out_of_bounds" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/unused_array_set_unknown_index_out_of_bounds/Prover.toml b/test_programs/execution_failure/unused_array_set_unknown_index_out_of_bounds/Prover.toml new file mode 100644 index 00000000000..1ec81884d61 --- /dev/null +++ b/test_programs/execution_failure/unused_array_set_unknown_index_out_of_bounds/Prover.toml @@ -0,0 +1 @@ +x = "10" \ No newline at end of file diff --git a/test_programs/execution_failure/unused_array_set_unknown_index_out_of_bounds/src/main.nr b/test_programs/execution_failure/unused_array_set_unknown_index_out_of_bounds/src/main.nr new file mode 100644 index 00000000000..dbde898f7a9 --- /dev/null +++ b/test_programs/execution_failure/unused_array_set_unknown_index_out_of_bounds/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: Field) { + let mut array = [1, 2, 3]; + array[x] = 1; // Index out of bounds +} diff --git a/test_programs/execution_failure/unused_slice_get_known_index_out_of_bounds/Nargo.toml b/test_programs/execution_failure/unused_slice_get_known_index_out_of_bounds/Nargo.toml new file mode 100644 index 00000000000..f2acfa4d4cf --- /dev/null +++ b/test_programs/execution_failure/unused_slice_get_known_index_out_of_bounds/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unused_slice_get_known_index_out_of_bounds" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/unused_slice_get_known_index_out_of_bounds/Prover.toml b/test_programs/execution_failure/unused_slice_get_known_index_out_of_bounds/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/execution_failure/unused_slice_get_known_index_out_of_bounds/src/main.nr b/test_programs/execution_failure/unused_slice_get_known_index_out_of_bounds/src/main.nr new file mode 100644 index 00000000000..59e57664bbe --- /dev/null +++ b/test_programs/execution_failure/unused_slice_get_known_index_out_of_bounds/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + let slice = &[1, 2, 3]; + let _ = slice[10]; // Index out of bounds +} diff --git a/test_programs/execution_failure/unused_slice_get_unknown_index_out_of_bounds/Nargo.toml b/test_programs/execution_failure/unused_slice_get_unknown_index_out_of_bounds/Nargo.toml new file mode 100644 index 00000000000..3c8ae8fe07a --- /dev/null +++ b/test_programs/execution_failure/unused_slice_get_unknown_index_out_of_bounds/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unused_slice_get_unknown_index_out_of_bounds" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_failure/unused_slice_get_unknown_index_out_of_bounds/Prover.toml b/test_programs/execution_failure/unused_slice_get_unknown_index_out_of_bounds/Prover.toml new file mode 100644 index 00000000000..1ec81884d61 --- /dev/null +++ b/test_programs/execution_failure/unused_slice_get_unknown_index_out_of_bounds/Prover.toml @@ -0,0 +1 @@ +x = "10" \ No newline at end of file diff --git a/test_programs/execution_failure/unused_slice_get_unknown_index_out_of_bounds/src/main.nr b/test_programs/execution_failure/unused_slice_get_unknown_index_out_of_bounds/src/main.nr new file mode 100644 index 00000000000..5a62e0e9843 --- /dev/null +++ b/test_programs/execution_failure/unused_slice_get_unknown_index_out_of_bounds/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: Field) { + let slice = &[1, 2, 3]; + let _ = slice[x]; // Index out of bounds +} diff --git a/test_programs/execution_failure/workspace_fail/Nargo.toml b/test_programs/execution_failure/workspace_fail/Nargo.toml new file mode 100644 index 00000000000..36db098686f --- /dev/null +++ b/test_programs/execution_failure/workspace_fail/Nargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["crates/a", "crates/b"] diff --git a/test_programs/execution_failure/workspace_fail/crates/a/Nargo.toml b/test_programs/execution_failure/workspace_fail/crates/a/Nargo.toml new file mode 100644 index 00000000000..8d0e1aca4a9 --- /dev/null +++ b/test_programs/execution_failure/workspace_fail/crates/a/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "a" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_failure/workspace_fail/crates/a/Prover.toml b/test_programs/execution_failure/workspace_fail/crates/a/Prover.toml new file mode 100644 index 00000000000..b76c88bf536 --- /dev/null +++ b/test_programs/execution_failure/workspace_fail/crates/a/Prover.toml @@ -0,0 +1,3 @@ +# Deliberately setting these to fail to prove this is being executed +x = "1" +y = "2" diff --git a/test_programs/execution_failure/workspace_fail/crates/a/src/main.nr b/test_programs/execution_failure/workspace_fail/crates/a/src/main.nr new file mode 100644 index 00000000000..cf72627da2e --- /dev/null +++ b/test_programs/execution_failure/workspace_fail/crates/a/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x == y); +} diff --git a/test_programs/execution_failure/workspace_fail/crates/b/Nargo.toml b/test_programs/execution_failure/workspace_fail/crates/b/Nargo.toml new file mode 100644 index 00000000000..f316511340f --- /dev/null +++ b/test_programs/execution_failure/workspace_fail/crates/b/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "b" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_failure/workspace_fail/crates/b/Prover.toml b/test_programs/execution_failure/workspace_fail/crates/b/Prover.toml new file mode 100644 index 00000000000..a0397e89477 --- /dev/null +++ b/test_programs/execution_failure/workspace_fail/crates/b/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "0" diff --git a/test_programs/execution_failure/workspace_fail/crates/b/src/main.nr b/test_programs/execution_failure/workspace_fail/crates/b/src/main.nr new file mode 100644 index 00000000000..4e1fd3c9035 --- /dev/null +++ b/test_programs/execution_failure/workspace_fail/crates/b/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x != y); +} diff --git a/test_programs/execution_report.sh b/test_programs/execution_report.sh new file mode 100755 index 00000000000..827b7806d37 --- /dev/null +++ b/test_programs/execution_report.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +set -e + +PARSE_TIME=$(realpath "$(dirname "$0")/parse_time.sh") +current_dir=$(pwd) +base_path="$current_dir/execution_success" + +# Tests to be profiled for execution report +tests_to_profile=("sha256_regression" "regression_4709" "ram_blowup_regression") + +echo "{\"execution_reports\": [ " > $current_dir/execution_report.json + +# If there is an argument that means we want to generate a report for only the current directory +if [ "$1" == "1" ]; then + base_path="$current_dir" + tests_to_profile=(".") +fi + +ITER="1" +NUM_ARTIFACTS=${#tests_to_profile[@]} + +for dir in ${tests_to_profile[@]}; do + if [[ " ${excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + if [[ ${CI-false} = "true" ]] && [[ " ${ci_excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + cd $base_path/$dir + + # The default package to run is the supplied list hardcoded at the top of the script + PACKAGE_NAME=$dir + # Otherwise default to the current directory as the package we want to run + if [ "$1" == "1" ]; then + PACKAGE_NAME=$(basename $current_dir) + fi + + # Check whether a compilation artifact exists. + # Any programs part of this benchmark should already be compiled. + # We want to make sure that compilation time is not included in the execution time. + if [ ! -e ./target/*.json ]; then + echo "Missing compilation artifact for $PACKAGE_NAME" + exit 1 + fi + + + NUM_RUNS=$2 + TOTAL_TIME=0 + + for ((i = 1; i <= NUM_RUNS; i++)); do + NOIR_LOG=trace NARGO_LOG_DIR=./tmp nargo execute --silence-warnings + done + + TIMES=($(jq -r '. | select(.target == "nargo::ops::execute" and .fields.message == "close") | .fields."time.busy"' ./tmp/*)) + + AVG_TIME=$(awk -v RS=" " -v parse_time="$PARSE_TIME" ' + { + # Times are formatted annoyingly so we need to parse it. + parse_time" "$1 | getline current_time + close(parse_time" "$1) + sum += current_time; + n++; + } + END { + if (n > 0) + printf "%.3f\n", sum / n + else + printf "%.3f\n", 0 + }' <<<"${TIMES[@]}") + + jq -rc "{artifact_name: \"$PACKAGE_NAME\", time: \""$AVG_TIME"s\"}" --null-input >> $current_dir/execution_report.json + + if (($ITER != $NUM_ARTIFACTS)); then + echo "," >> $current_dir/execution_report.json + fi + + rm -rf ./tmp + + ITER=$(( $ITER + 1 )) +done + +echo "]}" >> $current_dir/execution_report.json diff --git a/test_programs/execution_success/1327_concrete_in_generic/Nargo.toml b/test_programs/execution_success/1327_concrete_in_generic/Nargo.toml new file mode 100644 index 00000000000..3adf969538c --- /dev/null +++ b/test_programs/execution_success/1327_concrete_in_generic/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "1327_concrete_in_generic" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/1327_concrete_in_generic/Prover.toml b/test_programs/execution_success/1327_concrete_in_generic/Prover.toml new file mode 100644 index 00000000000..e5fc42da053 --- /dev/null +++ b/test_programs/execution_success/1327_concrete_in_generic/Prover.toml @@ -0,0 +1 @@ +input = 1 \ No newline at end of file diff --git a/test_programs/execution_success/1327_concrete_in_generic/src/main.nr b/test_programs/execution_success/1327_concrete_in_generic/src/main.nr new file mode 100644 index 00000000000..1d37eca57a2 --- /dev/null +++ b/test_programs/execution_success/1327_concrete_in_generic/src/main.nr @@ -0,0 +1,64 @@ +// --- +fn new_concrete_c_over_d() -> C { + let d_method_interface = get_d_method_interface(); + C::new(d_method_interface) +} +// --- +// Map +struct B { + new_concrete_t_c_constructor: fn() -> T_C, +} + +impl B { + fn new(new_concrete_t_c_constructor: fn() -> T_C) -> B { + B { new_concrete_t_c_constructor } + } + + fn get_t_c(self) -> T_C { + let new_concrete_t_c_constructor = self.new_concrete_t_c_constructor; + new_concrete_t_c_constructor() + } +} +// --- +// PrivateSet +struct C { + t_d_interface: MethodInterface, +} + +impl C { + fn new(t_d_interface: MethodInterface) -> Self { + C { t_d_interface } + } + + fn call_method_of_t_d(self, t_d: T_D) -> Field { + let some_method_on_t_d = self.t_d_interface.some_method_on_t_d; + some_method_on_t_d(t_d) + } +} +// --- +struct MethodInterface { + some_method_on_t_d: fn(T_D) -> Field, +} +// --- +// Note +struct D { + d: Field, +} + +fn d_method(input: D) -> Field { + input.d * input.d +} + +fn get_d_method_interface() -> MethodInterface { + MethodInterface { some_method_on_t_d: d_method } +} +// --- +fn main(input: Field) -> pub Field { + let b: B> = B::new(new_concrete_c_over_d); + let c: C = b.get_t_c(); // PrivateMutable + let d: D = D { d: input }; // Note + let output = c.call_method_of_t_d(d); + + output +} +// --- diff --git a/test_programs/execution_success/1_mul/Nargo.toml b/test_programs/execution_success/1_mul/Nargo.toml new file mode 100644 index 00000000000..94b36157cca --- /dev/null +++ b/test_programs/execution_success/1_mul/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "1_mul" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/1_mul/Prover.toml b/test_programs/execution_success/1_mul/Prover.toml new file mode 100644 index 00000000000..9bff601c75a --- /dev/null +++ b/test_programs/execution_success/1_mul/Prover.toml @@ -0,0 +1,3 @@ +x = "3" +y = "4" +z = "429981696" diff --git a/test_programs/execution_success/1_mul/src/main.nr b/test_programs/execution_success/1_mul/src/main.nr new file mode 100644 index 00000000000..8f4032dbd75 --- /dev/null +++ b/test_programs/execution_success/1_mul/src/main.nr @@ -0,0 +1,9 @@ +// Test unsafe integer multiplication with overflow: 12^8 = 429 981 696 +// The circuit should handle properly the growth of the bit size +fn main(mut x: u32, y: u32, z: u32) { + x *= y; + x *= x; //144 + x *= x; //20736 + x *= x; //429 981 696 + assert(x == z); +} diff --git a/test_programs/execution_success/2_div/Nargo.toml b/test_programs/execution_success/2_div/Nargo.toml new file mode 100644 index 00000000000..f689c97f760 --- /dev/null +++ b/test_programs/execution_success/2_div/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "2_div" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/2_div/Prover.toml b/test_programs/execution_success/2_div/Prover.toml new file mode 100644 index 00000000000..ee6f0ef229a --- /dev/null +++ b/test_programs/execution_success/2_div/Prover.toml @@ -0,0 +1,3 @@ +x = "7" +y = "3" +z = "2" \ No newline at end of file diff --git a/test_programs/execution_success/2_div/src/main.nr b/test_programs/execution_success/2_div/src/main.nr new file mode 100644 index 00000000000..e16cc5be229 --- /dev/null +++ b/test_programs/execution_success/2_div/src/main.nr @@ -0,0 +1,7 @@ +// Testing integer division: 7/3 = 2 +fn main(mut x: u32, y: u32, z: u32) { + let a = x % y; + assert(x / y == z); + assert(a == x - z * y); + assert((50 as u64) % (9 as u64) == 5); +} diff --git a/test_programs/execution_success/3_add/Nargo.toml b/test_programs/execution_success/3_add/Nargo.toml new file mode 100644 index 00000000000..0bd2caef024 --- /dev/null +++ b/test_programs/execution_success/3_add/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "3_add" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/3_add/Prover.toml b/test_programs/execution_success/3_add/Prover.toml new file mode 100644 index 00000000000..5d777c023db --- /dev/null +++ b/test_programs/execution_success/3_add/Prover.toml @@ -0,0 +1,3 @@ +x = "3" +y = "4" +z = "7" \ No newline at end of file diff --git a/test_programs/execution_success/3_add/src/main.nr b/test_programs/execution_success/3_add/src/main.nr new file mode 100644 index 00000000000..480348dc1cf --- /dev/null +++ b/test_programs/execution_success/3_add/src/main.nr @@ -0,0 +1,8 @@ +// Test integer addition: 3 + 4 = 7 +fn main(mut x: u32, y: u32, z: u32) { + x += y; + assert(x == z); + + x *= 8; + assert(x > 9); +} diff --git a/test_programs/execution_success/4_sub/Nargo.toml b/test_programs/execution_success/4_sub/Nargo.toml new file mode 100644 index 00000000000..b282bfe6287 --- /dev/null +++ b/test_programs/execution_success/4_sub/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "4_sub" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/4_sub/Prover.toml b/test_programs/execution_success/4_sub/Prover.toml new file mode 100644 index 00000000000..1240475dee3 --- /dev/null +++ b/test_programs/execution_success/4_sub/Prover.toml @@ -0,0 +1,3 @@ +x = "12" +y = "2418266113" +z = "1876701195" \ No newline at end of file diff --git a/test_programs/execution_success/4_sub/src/main.nr b/test_programs/execution_success/4_sub/src/main.nr new file mode 100644 index 00000000000..4170c2cbaf2 --- /dev/null +++ b/test_programs/execution_success/4_sub/src/main.nr @@ -0,0 +1,5 @@ +// Test unsafe integer subtraction with underflow: 12 - 2418266113 = 1876701195 modulo 2^32 +fn main(mut x: u32, y: u32, z: u32) { + x = std::wrapping_sub(x, y); + assert(x == z); +} diff --git a/test_programs/execution_success/5_over/Nargo.toml b/test_programs/execution_success/5_over/Nargo.toml new file mode 100644 index 00000000000..dd9a21b44bf --- /dev/null +++ b/test_programs/execution_success/5_over/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "5_over" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/5_over/Prover.toml b/test_programs/execution_success/5_over/Prover.toml new file mode 100644 index 00000000000..9a1986329ca --- /dev/null +++ b/test_programs/execution_success/5_over/Prover.toml @@ -0,0 +1,2 @@ +x = "43046721" +y = "3793632897" diff --git a/test_programs/execution_success/5_over/src/main.nr b/test_programs/execution_success/5_over/src/main.nr new file mode 100644 index 00000000000..ad0a60d0a7f --- /dev/null +++ b/test_programs/execution_success/5_over/src/main.nr @@ -0,0 +1,9 @@ +// Test unsafe integer arithmetic +// Test odd bits integer +fn main(mut x: u32, y: u32) { + x = std::wrapping_mul(x, x); + assert(y == x); + + let c: u1 = 0; + assert(x as u1 > c); +} diff --git a/test_programs/execution_success/6/Nargo.toml b/test_programs/execution_success/6/Nargo.toml new file mode 100644 index 00000000000..9774a5d8c47 --- /dev/null +++ b/test_programs/execution_success/6/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "6" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/6/Prover.toml b/test_programs/execution_success/6/Prover.toml new file mode 100644 index 00000000000..1c52aef063c --- /dev/null +++ b/test_programs/execution_success/6/Prover.toml @@ -0,0 +1,39 @@ + +# hello as bytes +# used : https://emn178.github.io/online-tools/sha256.html +x = [104, 101, 108, 108, 111] + +result = [ + 0x2c, + 0xf2, + 0x4d, + 0xba, + 0x5f, + 0xb0, + 0xa3, + 0x0e, + 0x26, + 0xe8, + 0x3b, + 0x2a, + 0xc5, + 0xb9, + 0xe2, + 0x9e, + 0x1b, + 0x16, + 0x1e, + 0x5c, + 0x1f, + 0xa7, + 0x42, + 0x5e, + 0x73, + 0x04, + 0x33, + 0x62, + 0x93, + 0x8b, + 0x98, + 0x24, +] diff --git a/test_programs/execution_success/6/src/main.nr b/test_programs/execution_success/6/src/main.nr new file mode 100644 index 00000000000..5b71174614f --- /dev/null +++ b/test_programs/execution_success/6/src/main.nr @@ -0,0 +1,11 @@ +// Sha256 circuit where the input is 5 bytes +// not five field elements since sha256 operates over +// bytes. +// +// If you do not cast, it will take all the bytes from the field element! +fn main(x: [u8; 5], result: pub [u8; 32]) { + let mut digest = std::hash::sha256(x); + digest[0] = 5 as u8; + digest = std::hash::sha256(x); + assert(digest == result); +} diff --git a/test_programs/execution_success/6_array/Nargo.toml b/test_programs/execution_success/6_array/Nargo.toml new file mode 100644 index 00000000000..c75df3e468e --- /dev/null +++ b/test_programs/execution_success/6_array/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "6_array" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/6_array/Prover.toml b/test_programs/execution_success/6_array/Prover.toml new file mode 100644 index 00000000000..2e2ed310ba1 --- /dev/null +++ b/test_programs/execution_success/6_array/Prover.toml @@ -0,0 +1,8 @@ +x = [104, 101, 108, 108, 111] +y = [10, 81, 18, 48, 0] +z = "59" +t = "10" + +#7128 +#15309 +#16349 \ No newline at end of file diff --git a/test_programs/execution_success/6_array/src/main.nr b/test_programs/execution_success/6_array/src/main.nr new file mode 100644 index 00000000000..37f6e447487 --- /dev/null +++ b/test_programs/execution_success/6_array/src/main.nr @@ -0,0 +1,52 @@ +//Basic tests for arrays +fn main(x: [u32; 5], y: [u32; 5], mut z: u32, t: u32) { + let mut c = 2301; + z = y[4]; + //Test 1: + for i in 0..5 { + c = z * z * y[i]; + z -= c; + } + assert(z == 0); //y[4]=0, so c and z are always 0 + //Test 2: + c = 2301 as u32; + for i in 0..5 { + c = t + 2 as u32; + c = std::wrapping_mul(std::wrapping_mul(z, z), x[i]); + z = std::wrapping_add(z, std::wrapping_sub(x[i] * y[i], c)); + } + assert(z == 3814912846); + //Test 3: + c = 2300001 as u32; + z = y[4]; + for i in 0..5 { + z = z + x[i] * y[i]; + for _i in 0..3 { + c = std::wrapping_sub(i as u32, 2 as u32); + z = std::wrapping_mul(z, c); + } + } + assert(z == 41472); + //Test 4: + z = y[4]; + for i in 0..3 { + z += x[i] * y[i]; + for j in 0..2 { + z += x[i + j] - y[i + j]; + } + } + assert(z == 11539); + //Test 5: + let cc = if z < 1 { x } else { y }; + assert(cc[0] == y[0]); + // Test 6: for-each loops + for y_elem in y { + for x_elem in x { + assert(x_elem != y_elem); + } + } + // Test 7: Arrays of tuples/structs + let mut tuple_array = [(1, 2), (3, 4), (5, 6)]; + tuple_array[1] = (7, 8); + assert(tuple_array[1].1 == 8); +} diff --git a/test_programs/execution_success/7/Nargo.toml b/test_programs/execution_success/7/Nargo.toml new file mode 100644 index 00000000000..f69f89468d7 --- /dev/null +++ b/test_programs/execution_success/7/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "7" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/7/Prover.toml b/test_programs/execution_success/7/Prover.toml new file mode 100644 index 00000000000..bc3784726d2 --- /dev/null +++ b/test_programs/execution_success/7/Prover.toml @@ -0,0 +1,38 @@ + +# hello as bytes +# https://toolkitbay.com/tkb/tool/BLAKE2s_256 +x = [104, 101, 108, 108, 111] +result = [ + 0x19, + 0x21, + 0x3b, + 0xac, + 0xc5, + 0x8d, + 0xee, + 0x6d, + 0xbd, + 0xe3, + 0xce, + 0xb9, + 0xa4, + 0x7c, + 0xbb, + 0x33, + 0x0b, + 0x3d, + 0x86, + 0xf8, + 0xcc, + 0xa8, + 0x99, + 0x7e, + 0xb0, + 0x0b, + 0xe4, + 0x56, + 0xf1, + 0x40, + 0xca, + 0x25, +] diff --git a/test_programs/execution_success/7/src/main.nr b/test_programs/execution_success/7/src/main.nr new file mode 100644 index 00000000000..32880aa8e41 --- /dev/null +++ b/test_programs/execution_success/7/src/main.nr @@ -0,0 +1,8 @@ +// This is the same as Blake2s example. +// +// Pre-alpha dependencies must now be prefixed with the word "dep". +// The line below indicates that we would like to pull in the standard library dependency. +fn main(x: [u8; 5], result: [u8; 32]) { + let digest = std::hash::blake2s(x); + assert(digest == result); +} diff --git a/test_programs/execution_success/7_function/Nargo.toml b/test_programs/execution_success/7_function/Nargo.toml new file mode 100644 index 00000000000..cec14ff7d6a --- /dev/null +++ b/test_programs/execution_success/7_function/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "7_function" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/7_function/Prover.toml b/test_programs/execution_success/7_function/Prover.toml new file mode 100644 index 00000000000..9140e7f7530 --- /dev/null +++ b/test_programs/execution_success/7_function/Prover.toml @@ -0,0 +1,6 @@ +x = "59" +y = "5" +a = "1" + +arr1=[3320379920, 1938147428, 1942509796, 1795943184, 24853, 0, 0, 0, 0] +arr2=[2912727897, 3590519536, 1687587470, 3896107618, 1092831095, 0, 0, 0, 0] \ No newline at end of file diff --git a/test_programs/execution_success/7_function/src/main.nr b/test_programs/execution_success/7_function/src/main.nr new file mode 100644 index 00000000000..ad065a5cae5 --- /dev/null +++ b/test_programs/execution_success/7_function/src/main.nr @@ -0,0 +1,139 @@ +//Tests for function calling +fn f1(mut x: Field) -> Field { + x = x + 1; + x = f2(x); + x +} + +fn f2(mut x: Field) -> Field { + x += 2; + x +} +// Simple example +fn test0(mut a: Field) { + a = f2(a); + assert(a == 3); +} +// Nested call +fn test1(mut a: Field) { + a = f1(a); + assert(a == 4); +} + +fn test2(z: Field, t: u32) { + let a = z + t as Field; + assert(a == 64); + let e = pow(z, t as Field); + assert(e == 714924299); +} + +fn pow(base: Field, exponent: Field) -> Field { + let mut r = 1 as Field; + let b: [u1; 32] = exponent.to_le_bits(); + for i in 1..33 { + r = r * r; + r = (b[32 - i] as Field) * (r * base) + (1 - b[32 - i] as Field) * r; + } + r +} + +fn test3(x: [u8; 3]) -> [u8; 3] { + let mut buffer = [0 as u8; 3]; + for i in 0..3 { + buffer[i] = x[i]; + } + assert(buffer == x); + buffer +} + +fn test_multiple(x: u32, y: u32) -> (u32, u32) { + (y, x) +} + +fn test_multiple2() -> my_struct { + my_struct { a: 5 as u32, b: 7 as u32 } +} + +fn test_multiple3(x: u32, y: u32) { + assert(x == y); +} + +struct my_struct { + a: u32, + b: u32, +} + +struct my2 { + aa: my_struct, + bb: my_struct, +} + +fn test_multiple4(s: my_struct) { + assert(s.a == s.b + 2); +} + +fn test_multiple5(a: (u32, u32)) { + assert(a.0 == a.1 + 2); +} + +fn test_multiple6(a: my2, b: my_struct, c: (my2, my_struct)) { + test_multiple4(a.aa); + test_multiple5((b.a, b.b)); + assert(c.0.aa.a == c.1.a); +} + +fn foo(a: [Field; N]) -> [Field; N] { + a +} + +fn bar() -> [Field; 1] { + foo([0]) +} + +fn main(x: u32, y: u32, a: Field, arr1: [u32; 9], arr2: [u32; 9]) { + let mut ss: my_struct = my_struct { b: x, a: x + 2 }; + test_multiple4(ss); + test_multiple5((ss.a, ss.b)); + let my = my2 { aa: ss, bb: ss }; + ss.a = 61; + test_multiple6(my, ss, (my, ss)); + + let my_block = { + let mut ab = f2(a); + ab = ab + a; + (x, ab) + }; + assert(my_block.1 == 4); + + test0(a); + test1(a); + test2(x as Field, y); + assert(bar()[0] == 0); + + let mut b = [0 as u8, 5 as u8, 2 as u8]; + let c = test3(b); + assert(b == c); + b[0] = 1 as u8; + let cc = test3(b); + assert(c != cc); + let e = test_multiple(x, y); + assert(e.1 == e.0 + 54 as u32); + let d = test_multiple2(); + assert(d.b == d.a + 2 as u32); + test_multiple3(y, y); + //Regression test for issue #628: + let result = first(arr_to_field(arr1), arr_to_field(arr2)); + assert(result[0] == arr1[0] as Field); +} +// Issue #628 +fn arr_to_field(arr: [u32; 9]) -> [Field; 9] { + let mut as_field: [Field; 9] = [0 as Field; 9]; + for i in 0..9 { + as_field[i] = arr[i] as Field; + } + as_field +} + +fn first(a: [Field; 9], _b: [Field; 9]) -> [Field; 9] { + a +} 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..11f9512444e --- /dev/null +++ b/test_programs/execution_success/aes128_encrypt/src/main.nr @@ -0,0 +1,39 @@ +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 result = std::aes128::aes128_encrypt(plaintext, iv, key); + result +} + +fn main(inputs: str<12>, iv: str<16>, key: str<16>, output: str<32>) { + let result: [u8; 16] = + std::aes128::aes128_encrypt(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()); + + /// Safety: testing context + let output_bytes: [u8; 16] = unsafe { decode_hex(output) }; + assert(result == output_bytes); + + /// Safety: testing context + let unconstrained_result = unsafe { cipher(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()) }; + assert(unconstrained_result == output_bytes); +} diff --git a/test_programs/execution_success/arithmetic_binary_operations/Nargo.toml b/test_programs/execution_success/arithmetic_binary_operations/Nargo.toml new file mode 100644 index 00000000000..c9160aa2592 --- /dev/null +++ b/test_programs/execution_success/arithmetic_binary_operations/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "arithmetic_binary_operations" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/arithmetic_binary_operations/Prover.toml b/test_programs/execution_success/arithmetic_binary_operations/Prover.toml new file mode 100644 index 00000000000..63382a9f640 --- /dev/null +++ b/test_programs/execution_success/arithmetic_binary_operations/Prover.toml @@ -0,0 +1,3 @@ +x = "3" +y = "4" +z = "5" diff --git a/test_programs/execution_success/arithmetic_binary_operations/src/main.nr b/test_programs/execution_success/arithmetic_binary_operations/src/main.nr new file mode 100644 index 00000000000..3a6b0149ec1 --- /dev/null +++ b/test_programs/execution_success/arithmetic_binary_operations/src/main.nr @@ -0,0 +1,15 @@ +// Tests a very simple program. +// +// The features being tested are: +// Binary addition, multiplication, division, constant modulo +// x = 3, y = 4, z = 5 +fn main(x: Field, y: Field, z: Field) -> pub Field { + //cast + assert(y as u1 == 0); + + let a = x + x; // 3 + 3 = 6 + let b = a - y; // 6 - 4 = 2 + let c = b * z; // 2 * 5 = 10 + let d = c / a; // 10 / 6 (This uses field inversion, so we test it by multiplying by `a`) + d * a +} diff --git a/test_programs/execution_success/array_dedup_regression/Nargo.toml b/test_programs/execution_success/array_dedup_regression/Nargo.toml new file mode 100644 index 00000000000..16a708743ed --- /dev/null +++ b/test_programs/execution_success/array_dedup_regression/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "array_dedup_regression" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/array_dedup_regression/Prover.toml b/test_programs/execution_success/array_dedup_regression/Prover.toml new file mode 100644 index 00000000000..3aea0c58ce5 --- /dev/null +++ b/test_programs/execution_success/array_dedup_regression/Prover.toml @@ -0,0 +1 @@ +x = 0 diff --git a/test_programs/execution_success/array_dedup_regression/src/main.nr b/test_programs/execution_success/array_dedup_regression/src/main.nr new file mode 100644 index 00000000000..5506d55b9e7 --- /dev/null +++ b/test_programs/execution_success/array_dedup_regression/src/main.nr @@ -0,0 +1,21 @@ +unconstrained fn main(x: u32) { + let a1 = [1, 2, 3, 4, 5]; + + for i in 0..5 { + let mut a2 = [1, 2, 3, 4, 5]; + a2[x + i] = 128; + println(a2); + + if i != 0 { + assert(a2[x + i - 1] != 128); + } + } + + // Can't use `== [1, 2, 3, 4, 5]` here, that make_array may get + // deduplicated to equal a1 in the bugged version + assert_eq(a1[0], 1); + assert_eq(a1[1], 2); + assert_eq(a1[2], 3); + assert_eq(a1[3], 4); + assert_eq(a1[4], 5); +} diff --git a/test_programs/execution_success/array_dynamic/Nargo.toml b/test_programs/execution_success/array_dynamic/Nargo.toml new file mode 100644 index 00000000000..25684b00377 --- /dev/null +++ b/test_programs/execution_success/array_dynamic/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "array_dynamic" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/array_dynamic/Prover.toml b/test_programs/execution_success/array_dynamic/Prover.toml new file mode 100644 index 00000000000..750b3129ec9 --- /dev/null +++ b/test_programs/execution_success/array_dynamic/Prover.toml @@ -0,0 +1,9 @@ +x = [104, 101, 108, 108, 111] +z = "59" +t = "10" +index = [0,1,2,3,4] +index2 = [0,1,2,3,4] +offset = 1 +sublen = 2 + + diff --git a/test_programs/execution_success/array_dynamic/src/main.nr b/test_programs/execution_success/array_dynamic/src/main.nr new file mode 100644 index 00000000000..fc29c4364c9 --- /dev/null +++ b/test_programs/execution_success/array_dynamic/src/main.nr @@ -0,0 +1,38 @@ +fn main( + x: [u32; 5], + mut z: u32, + t: u32, + index: [Field; 5], + index2: [Field; 5], + offset: Field, + sublen: Field, +) { + let idx = (z - 5 * t - 5) as Field; + //dynamic array test + dyn_array(x, idx, idx - 3); + //regression for issue 1283 + let mut s = 0; + let x3 = [246, 159, 32, 176, 8]; + for i in 0..5 { + s += x3[index[i]]; + } + assert(s != 0); + + if 3 < (sublen as u32) { + assert(index[offset + 3] == index2[3]); + } +} + +fn dyn_array(mut x: [u32; 5], y: Field, z: Field) { + assert(x[y] == 111); + assert(x[z] == 101); + x[z] = 0; + assert(x[y] == 111); + assert(x[1] == 0); + if y as u32 < 10 { + x[y] = x[y] - 2; + } else { + x[y] = 0; + } + assert(x[4] == 109); +} diff --git a/test_programs/execution_success/array_dynamic_blackbox_input/Nargo.toml b/test_programs/execution_success/array_dynamic_blackbox_input/Nargo.toml new file mode 100644 index 00000000000..03da304acc3 --- /dev/null +++ b/test_programs/execution_success/array_dynamic_blackbox_input/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "array_dynamic_blackbox_input" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/array_dynamic_blackbox_input/Prover.toml b/test_programs/execution_success/array_dynamic_blackbox_input/Prover.toml new file mode 100644 index 00000000000..cc60eb8a8ba --- /dev/null +++ b/test_programs/execution_success/array_dynamic_blackbox_input/Prover.toml @@ -0,0 +1,4 @@ +index = "1" +leaf = ["51", "109", "224", "175", "60", "42", "79", "222", "117", "255", "174", "79", "126", "242", "74", "34", "100", "35", "20", "200", "109", "89", "191", "219", "41", "10", "118", "217", "165", "224", "215", "109"] +path = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63"] +root = [79, 230, 126, 184, 98, 125, 226, 58, 117, 45, 140, 15, 72, 118, 89, 173, 117, 161, 166, 0, 214, 125, 13, 16, 113, 81, 173, 156, 97, 15, 57, 216] diff --git a/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr b/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr new file mode 100644 index 00000000000..260d609928b --- /dev/null +++ b/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr @@ -0,0 +1,27 @@ +fn main(leaf: [u8; 32], path: [u8; 64], index: u32, root: [u8; 32]) { + compute_root(leaf, path, index, root); +} + +fn compute_root(leaf: [u8; 32], path: [u8; 64], _index: u32, root: [u8; 32]) { + let mut current = leaf; + let mut index = _index; + + for i in 0..2 { + let mut hash_input = [0; 64]; + let offset = i * 32; + let is_right = (index & 1) != 0; + let a = if is_right { 32 } else { 0 }; + let b = if is_right { 0 } else { 32 }; + + for j in 0..32 { + hash_input[j + a] = current[j]; + hash_input[j + b] = path[offset + j]; + } + + current = std::hash::sha256(hash_input); + index = index >> 1; + } + + // Regression for issue #4258 + assert(root == current); +} diff --git a/test_programs/execution_success/array_dynamic_main_output/Nargo.toml b/test_programs/execution_success/array_dynamic_main_output/Nargo.toml new file mode 100644 index 00000000000..b202b7aba0a --- /dev/null +++ b/test_programs/execution_success/array_dynamic_main_output/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "array_dynamic_main_output" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/array_dynamic_main_output/Prover.toml b/test_programs/execution_success/array_dynamic_main_output/Prover.toml new file mode 100644 index 00000000000..3f1d55b9b64 --- /dev/null +++ b/test_programs/execution_success/array_dynamic_main_output/Prover.toml @@ -0,0 +1,2 @@ +index = "5" +x = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] diff --git a/test_programs/execution_success/array_dynamic_main_output/src/main.nr b/test_programs/execution_success/array_dynamic_main_output/src/main.nr new file mode 100644 index 00000000000..50feb71f983 --- /dev/null +++ b/test_programs/execution_success/array_dynamic_main_output/src/main.nr @@ -0,0 +1,4 @@ +fn main(mut x: [Field; 10], index: u8) -> pub [Field; 10] { + x[index] = 0; + x +} diff --git a/test_programs/execution_success/array_dynamic_nested_blackbox_input/Nargo.toml b/test_programs/execution_success/array_dynamic_nested_blackbox_input/Nargo.toml new file mode 100644 index 00000000000..07d867d433f --- /dev/null +++ b/test_programs/execution_success/array_dynamic_nested_blackbox_input/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "array_dynamic_nested_blackbox_input" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/array_dynamic_nested_blackbox_input/Prover.toml b/test_programs/execution_success/array_dynamic_nested_blackbox_input/Prover.toml new file mode 100644 index 00000000000..1f291532414 --- /dev/null +++ b/test_programs/execution_success/array_dynamic_nested_blackbox_input/Prover.toml @@ -0,0 +1,23 @@ +y = "3" +hash_result = [50, 53, 90, 252, 105, 236, 223, 30, 135, 229, 193, 172, 51, 139, 8, 32, 188, 104, 151, 115, 129, 168, 27, 71, 203, 47, 40, 228, 89, 177, 129, 100] + +[[x]] +a = "1" +b = ["2", "3", "20"] + +[x.bar] +inner = ["100", "101", "102"] + +[[x]] +a = "4" # idx = 3, flattened start idx = 7 +b = ["5", "6", "21"] # idx = 4, flattened start idx = 8 + +[x.bar] +inner = ["103", "104", "105"] # idx = 5, flattened start idx = 11 + +[[x]] +a = "7" +b = ["8", "9", "22"] + +[x.bar] +inner = ["106", "107", "108"] \ No newline at end of file diff --git a/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr b/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr new file mode 100644 index 00000000000..15a2747eaa9 --- /dev/null +++ b/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr @@ -0,0 +1,20 @@ +struct Bar { + inner: [u8; 3], +} + +struct Foo { + a: Field, + b: [Field; 3], + bar: Bar, +} + +fn main(mut x: [Foo; 3], y: pub Field, hash_result: pub [u8; 32]) { + // Simple dynamic array set for entire inner most array + x[y - 1].bar.inner = [106, 107, 10]; + let mut hash_input = x[y - 1].bar.inner; + // Make sure that we are passing a dynamic array to the black box function call + // by setting the array using a dynamic index here + hash_input[y - 1] = 0; + let hash = std::hash::sha256(hash_input); + assert_eq(hash, hash_result); +} diff --git a/test_programs/execution_success/array_eq/Nargo.toml b/test_programs/execution_success/array_eq/Nargo.toml new file mode 100644 index 00000000000..1020d4905b1 --- /dev/null +++ b/test_programs/execution_success/array_eq/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "array_eq" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/array_eq/Prover.toml b/test_programs/execution_success/array_eq/Prover.toml new file mode 100644 index 00000000000..ecfed7de213 --- /dev/null +++ b/test_programs/execution_success/array_eq/Prover.toml @@ -0,0 +1,2 @@ +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/array_eq/src/main.nr b/test_programs/execution_success/array_eq/src/main.nr new file mode 100644 index 00000000000..5bbd595898c --- /dev/null +++ b/test_programs/execution_success/array_eq/src/main.nr @@ -0,0 +1,4 @@ +// Simple example of checking where two arrays are equal +fn main(a: [Field; 32], b: [Field; 32]) { + assert(a == b); +} 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/Nargo.toml b/test_programs/execution_success/array_len/Nargo.toml new file mode 100644 index 00000000000..24ac6ff7f13 --- /dev/null +++ b/test_programs/execution_success/array_len/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "array_len" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/array_len/Prover.toml b/test_programs/execution_success/array_len/Prover.toml new file mode 100644 index 00000000000..a5ffe607b73 --- /dev/null +++ b/test_programs/execution_success/array_len/Prover.toml @@ -0,0 +1,3 @@ +len3 = [1, 2, 3] +len4 = [1, 2, 3, 4] +x = 123 diff --git a/test_programs/execution_success/array_len/src/main.nr b/test_programs/execution_success/array_len/src/main.nr new file mode 100644 index 00000000000..d794690711a --- /dev/null +++ b/test_programs/execution_success/array_len/src/main.nr @@ -0,0 +1,24 @@ +fn len_plus_1(array: [T; N]) -> u32 { + array.len() + 1 +} + +fn add_lens(a: [T; N], b: [Field; M]) -> u32 { + a.len() + b.len() +} + +fn nested_call(b: [Field; N]) -> u32 { + len_plus_1(b) +} + +fn main(x: Field, len3: [u8; 3], len4: [Field; 4]) { + assert(len_plus_1(len3) == 4); + assert(len_plus_1(len4) == 5); + assert(add_lens(len3, len4) == 7); + assert(nested_call(len4) == 5); + // std::array::len returns a compile-time known value + assert(len4[len3.len()] == 4); + // Regression for #1023, ensure .len still works after calling to_le_bytes on a witness. + // This was needed because normally .len is evaluated before acir-gen where to_le_bytes + // on a witness is only evaluated during/after acir-gen. + assert(x.to_le_bytes::<8>().len() != 0); +} diff --git a/test_programs/execution_success/array_neq/Nargo.toml b/test_programs/execution_success/array_neq/Nargo.toml new file mode 100644 index 00000000000..2e4bbdf97ee --- /dev/null +++ b/test_programs/execution_success/array_neq/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "array_neq" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/array_neq/Prover.toml b/test_programs/execution_success/array_neq/Prover.toml new file mode 100644 index 00000000000..3aad77f6d4d --- /dev/null +++ b/test_programs/execution_success/array_neq/Prover.toml @@ -0,0 +1,2 @@ +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 = [44,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/array_neq/src/main.nr b/test_programs/execution_success/array_neq/src/main.nr new file mode 100644 index 00000000000..a3e51dc5066 --- /dev/null +++ b/test_programs/execution_success/array_neq/src/main.nr @@ -0,0 +1,4 @@ +// Simple example of checking where two arrays are different +fn main(a: [Field; 32], b: [Field; 32]) { + assert(a != b); +} diff --git a/test_programs/execution_success/array_sort/Nargo.toml b/test_programs/execution_success/array_sort/Nargo.toml new file mode 100644 index 00000000000..28e9c65a0dc --- /dev/null +++ b/test_programs/execution_success/array_sort/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "array_sort" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/array_sort/Prover.toml b/test_programs/execution_success/array_sort/Prover.toml new file mode 100644 index 00000000000..e0d79da4da6 --- /dev/null +++ b/test_programs/execution_success/array_sort/Prover.toml @@ -0,0 +1 @@ +xs = [2, 1, 3] diff --git a/test_programs/execution_success/array_sort/src/main.nr b/test_programs/execution_success/array_sort/src/main.nr new file mode 100644 index 00000000000..4f40a2cee84 --- /dev/null +++ b/test_programs/execution_success/array_sort/src/main.nr @@ -0,0 +1,6 @@ +fn main(xs: [u8; 3]) { + let sorted = xs.sort(); + assert(sorted[0] == 1); + assert(sorted[1] == 2); + assert(sorted[2] == 3); +} 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..3ca8bfff2ae --- /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..1d29db4973a --- /dev/null +++ b/test_programs/execution_success/array_to_slice_constant_length/src/main.nr @@ -0,0 +1,12 @@ +// 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) { + /// Safety: testing context + unsafe { + let array = return_array(val); + assert_constant(array.as_slice().len()); + } +} diff --git a/test_programs/execution_success/as_witness/Nargo.toml b/test_programs/execution_success/as_witness/Nargo.toml new file mode 100644 index 00000000000..18f3f99b5b5 --- /dev/null +++ b/test_programs/execution_success/as_witness/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "as_witness" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/as_witness/Prover.toml b/test_programs/execution_success/as_witness/Prover.toml new file mode 100644 index 00000000000..cd8a5b5e03c --- /dev/null +++ b/test_programs/execution_success/as_witness/Prover.toml @@ -0,0 +1 @@ +a = 42 \ No newline at end of file diff --git a/test_programs/execution_success/as_witness/src/main.nr b/test_programs/execution_success/as_witness/src/main.nr new file mode 100644 index 00000000000..a24f4af7669 --- /dev/null +++ b/test_programs/execution_success/as_witness/src/main.nr @@ -0,0 +1,5 @@ +// Simple example of checking where two arrays are different +fn main(a: Field) -> pub Field { + std::as_witness(a); + a +} diff --git a/test_programs/execution_success/assert/Nargo.toml b/test_programs/execution_success/assert/Nargo.toml new file mode 100644 index 00000000000..7780d53459e --- /dev/null +++ b/test_programs/execution_success/assert/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "assert" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/assert/Prover.toml b/test_programs/execution_success/assert/Prover.toml new file mode 100644 index 00000000000..4dd6b405159 --- /dev/null +++ b/test_programs/execution_success/assert/Prover.toml @@ -0,0 +1 @@ +x = "1" diff --git a/test_programs/execution_success/assert/src/main.nr b/test_programs/execution_success/assert/src/main.nr new file mode 100644 index 00000000000..b95665d502b --- /dev/null +++ b/test_programs/execution_success/assert/src/main.nr @@ -0,0 +1,10 @@ +fn main(x: Field) { + assert(x == 1); + assert(1 == conditional(x as bool)); +} + +fn conditional(x: bool) -> Field { + assert(x, f"Expected x to be true but got {x}"); + assert_eq(x, true, f"Expected x to be true but got {x}"); + 1 +} diff --git a/test_programs/execution_success/assert_statement/Nargo.toml b/test_programs/execution_success/assert_statement/Nargo.toml new file mode 100644 index 00000000000..c6a1daaed19 --- /dev/null +++ b/test_programs/execution_success/assert_statement/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "assert_statement" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/assert_statement/Prover.toml b/test_programs/execution_success/assert_statement/Prover.toml new file mode 100644 index 00000000000..5d1dc99124f --- /dev/null +++ b/test_programs/execution_success/assert_statement/Prover.toml @@ -0,0 +1,2 @@ +x = "3" +y = "3" diff --git a/test_programs/execution_success/assert_statement/src/main.nr b/test_programs/execution_success/assert_statement/src/main.nr new file mode 100644 index 00000000000..c076f047dd8 --- /dev/null +++ b/test_programs/execution_success/assert_statement/src/main.nr @@ -0,0 +1,7 @@ +// Tests a very simple program. +// +// The features being tested is assertion +fn main(x: Field, y: pub Field) { + assert(x == y, "x and y are not equal"); + assert_eq(x, y, "x and y are not equal"); +} diff --git a/test_programs/execution_success/assign_ex/Nargo.toml b/test_programs/execution_success/assign_ex/Nargo.toml new file mode 100644 index 00000000000..4ef7b3aa5a6 --- /dev/null +++ b/test_programs/execution_success/assign_ex/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "assign_ex" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/assign_ex/Prover.toml b/test_programs/execution_success/assign_ex/Prover.toml new file mode 100644 index 00000000000..8c12ebba6cf --- /dev/null +++ b/test_programs/execution_success/assign_ex/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "2" diff --git a/test_programs/execution_success/assign_ex/src/main.nr b/test_programs/execution_success/assign_ex/src/main.nr new file mode 100644 index 00000000000..b5cfc162cc4 --- /dev/null +++ b/test_programs/execution_success/assign_ex/src/main.nr @@ -0,0 +1,14 @@ +fn main(x: Field, y: Field) { + let mut z = x + y; + assert(z == 3); + z = x * y; + assert(z == 2); + + regression_3057(); +} +// Ensure parsing parenthesized lvalues works +fn regression_3057() { + let mut array = [[0, 1], [2, 3]]; + (array[0])[1] = 2; + assert(array[0][1] == 2); +} diff --git a/test_programs/execution_success/bench_2_to_17/Nargo.toml b/test_programs/execution_success/bench_2_to_17/Nargo.toml new file mode 100644 index 00000000000..47f49530483 --- /dev/null +++ b/test_programs/execution_success/bench_2_to_17/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_2_to_17" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/bench_2_to_17/Prover.toml b/test_programs/execution_success/bench_2_to_17/Prover.toml new file mode 100644 index 00000000000..2d35b0614e3 --- /dev/null +++ b/test_programs/execution_success/bench_2_to_17/Prover.toml @@ -0,0 +1 @@ +x = "3" \ No newline at end of file diff --git a/test_programs/execution_success/bench_2_to_17/src/main.nr b/test_programs/execution_success/bench_2_to_17/src/main.nr new file mode 100644 index 00000000000..204fbc38a16 --- /dev/null +++ b/test_programs/execution_success/bench_2_to_17/src/main.nr @@ -0,0 +1,8 @@ +use std::hash::poseidon2; + +global len: u32 = 2450 * 2; +fn main(x: Field) { + let ped_input = [x; len]; + let mut val = poseidon2::Poseidon2::hash(ped_input, len); + assert(val != 0); +} diff --git a/test_programs/execution_success/bench_ecdsa_secp256k1/Nargo.toml b/test_programs/execution_success/bench_ecdsa_secp256k1/Nargo.toml new file mode 100644 index 00000000000..7e83251cc5a --- /dev/null +++ b/test_programs/execution_success/bench_ecdsa_secp256k1/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_ecdsa_secp256k1" +description = "ECDSA secp256k1 verification" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/bench_ecdsa_secp256k1/Prover.toml b/test_programs/execution_success/bench_ecdsa_secp256k1/Prover.toml new file mode 100644 index 00000000000..e78fc19cb71 --- /dev/null +++ b/test_programs/execution_success/bench_ecdsa_secp256k1/Prover.toml @@ -0,0 +1,169 @@ + +hashed_message = [ + 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, +] +pub_key_x = [ + 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, +] +pub_key_y = [ + 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, +] +signature = [ + 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, +] diff --git a/test_programs/execution_success/bench_ecdsa_secp256k1/src/main.nr b/test_programs/execution_success/bench_ecdsa_secp256k1/src/main.nr new file mode 100644 index 00000000000..18d57d7886c --- /dev/null +++ b/test_programs/execution_success/bench_ecdsa_secp256k1/src/main.nr @@ -0,0 +1,7 @@ +use dep::std; + +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); +} diff --git a/test_programs/execution_success/bigint/Nargo.toml b/test_programs/execution_success/bigint/Nargo.toml new file mode 100644 index 00000000000..eee0920f188 --- /dev/null +++ b/test_programs/execution_success/bigint/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "bigint" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/bigint/Prover.toml b/test_programs/execution_success/bigint/Prover.toml new file mode 100644 index 00000000000..c50874a8613 --- /dev/null +++ b/test_programs/execution_success/bigint/Prover.toml @@ -0,0 +1,2 @@ +x = [34,3,5,8,4] +y = [44,7,1,8,8] \ No newline at end of file diff --git a/test_programs/execution_success/bigint/src/main.nr b/test_programs/execution_success/bigint/src/main.nr new file mode 100644 index 00000000000..2095c92349a --- /dev/null +++ b/test_programs/execution_success/bigint/src/main.nr @@ -0,0 +1,83 @@ +use std::bigint; +use 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 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 = std::field::bytes32_to_field(a_be_bytes); + let b_field = std::field::bytes32_to_field(b_be_bytes); + + // Regression for issue #4682 + let c = if x[0] != 0 { + test_unconstrained1(a, b) + } else { + /// Safety: testing context + unsafe { + test_unconstrained2(a, b) + } + }; + assert(c.array[0] == 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 = d - b; + let mut result = [0; 32]; + let result_slice: [u8; 32] = (a_field * b_field - b_field).to_le_bytes(); + 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/binary_operator_overloading/Nargo.toml b/test_programs/execution_success/binary_operator_overloading/Nargo.toml new file mode 100644 index 00000000000..a43f38bdf30 --- /dev/null +++ b/test_programs/execution_success/binary_operator_overloading/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "binary_operator_overloading" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] diff --git a/test_programs/execution_success/binary_operator_overloading/Prover.toml b/test_programs/execution_success/binary_operator_overloading/Prover.toml new file mode 100644 index 00000000000..516b7b4074c --- /dev/null +++ b/test_programs/execution_success/binary_operator_overloading/Prover.toml @@ -0,0 +1,2 @@ +x = 3 +y = 9 diff --git a/test_programs/execution_success/binary_operator_overloading/src/main.nr b/test_programs/execution_success/binary_operator_overloading/src/main.nr new file mode 100644 index 00000000000..03a4e1ed22f --- /dev/null +++ b/test_programs/execution_success/binary_operator_overloading/src/main.nr @@ -0,0 +1,150 @@ +use std::cmp::Ordering; +use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Rem, Shl, Shr, Sub}; + +// x = 3, y = 9 +fn main(x: u32, y: u32) { + let wx = Wrapper::new(x); + let wy = Wrapper::new(y); + + // expected x and expected y values + let ex: u32 = 3; + let ey: u32 = 9; + + assert((wx + wy).inner == ex + ey); + assert((wy - wx).inner == ey - ex); + assert((wx * wy).inner == ex * ey); + assert((wx / wy).inner == ex / ey); + assert((wx % wy).inner == ex % ey); + + assert((wx & wy).inner == (ex & ey)); + assert((wx | wy).inner == (ex | ey)); + assert((wx ^ wy).inner == (ex ^ ey)); + + 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)); + assert((wx <= wy) == (ex <= ey)); + assert((wx > wy) == (ex > ey)); + assert((wx >= wy) == (ex >= ey)); + assert(wx.cmp(wy) == ex.cmp(ey)); + + // Ensure operator overloading still works with more complex types + let pair_ascending = Pair { x: wx, y: wy }; + let pair_descending = Pair { x: wy, y: wx }; + + assert(pair_ascending != pair_descending); + + assert(pair_ascending < pair_descending); + assert(pair_ascending <= pair_descending); + assert(pair_descending > pair_ascending); + assert(pair_descending >= pair_ascending); + + assert(pair_ascending.cmp(pair_descending) == Ordering::less()); +} + +struct Wrapper { + inner: u32, +} + +impl Wrapper { + fn new(inner: u32) -> Self { + Wrapper { inner } + } +} + +impl Add for Wrapper { + fn add(self, other: Self) -> Self { + Wrapper::new(self.inner + other.inner) + } +} + +impl Sub for Wrapper { + fn sub(self, other: Self) -> Self { + Wrapper::new(self.inner - other.inner) + } +} + +impl Mul for Wrapper { + fn mul(self, other: Self) -> Self { + Wrapper::new(self.inner * other.inner) + } +} + +impl Div for Wrapper { + fn div(self, other: Self) -> Self { + Wrapper::new(self.inner / other.inner) + } +} + +impl Rem for Wrapper { + fn rem(self, other: Self) -> Self { + Wrapper::new(self.inner % other.inner) + } +} + +impl BitAnd for Wrapper { + fn bitand(self, other: Self) -> Self { + Wrapper::new(self.inner & other.inner) + } +} + +impl BitOr for Wrapper { + fn bitor(self, other: Self) -> Self { + Wrapper::new(self.inner | other.inner) + } +} + +impl BitXor for Wrapper { + fn bitxor(self, other: Self) -> Self { + Wrapper::new(self.inner ^ other.inner) + } +} + +impl Shl for Wrapper { + fn shl(self, other: u8) -> Self { + Wrapper::new(self.inner << other) + } +} + +impl Shr for Wrapper { + fn shr(self, other: u8) -> Self { + Wrapper::new(self.inner >> other) + } +} + +impl Eq for Wrapper { + fn eq(self, other: Self) -> bool { + self.inner == other.inner + } +} + +impl Ord for Wrapper { + fn cmp(self, other: Self) -> Ordering { + self.inner.cmp(other.inner) + } +} + +struct Pair { + x: Wrapper, + y: Wrapper, +} + +impl Eq for Pair { + fn eq(self, o: Self) -> bool { + (self.x == o.x) & (self.y == o.y) + } +} + +impl Ord for Pair { + fn cmp(self, o: Self) -> Ordering { + let mut result = self.x.cmp(o.x); + + if result == Ordering::equal() { + result = self.y.cmp(o.y); + } + + result + } +} diff --git a/test_programs/execution_success/bit_and/Nargo.toml b/test_programs/execution_success/bit_and/Nargo.toml new file mode 100644 index 00000000000..e9a28577079 --- /dev/null +++ b/test_programs/execution_success/bit_and/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "bit_and" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/bit_and/Prover.toml b/test_programs/execution_success/bit_and/Prover.toml new file mode 100644 index 00000000000..34a5b63e5b1 --- /dev/null +++ b/test_programs/execution_success/bit_and/Prover.toml @@ -0,0 +1,4 @@ +x = "0x00" +y = "0x10" +a = "0x00" +b = "0x10" diff --git a/test_programs/execution_success/bit_and/src/main.nr b/test_programs/execution_success/bit_and/src/main.nr new file mode 100644 index 00000000000..5a0aa17e3ed --- /dev/null +++ b/test_programs/execution_success/bit_and/src/main.nr @@ -0,0 +1,16 @@ +// You can only do bit operations with integers. +// (Kobi/Daira/Circom/#37) https://github.com/iden3/circom/issues/37 +fn main(x: Field, y: Field, a: Field, b: Field) { + let x_as_u8 = x as u8; + let y_as_u8 = y as u8; + + assert((x_as_u8 & y_as_u8) == x_as_u8); + //bitwise and with 1 bit: + let flag = (x == 0) & (y == 16); + assert(flag); + //bitwise and with odd bits: + let a_as_u8 = a as u8; + let b_as_u8 = b as u8; + assert((a_as_u8 & b_as_u8) == a_as_u8); +} + diff --git a/test_programs/execution_success/bit_not/Nargo.toml b/test_programs/execution_success/bit_not/Nargo.toml new file mode 100644 index 00000000000..e89a338595b --- /dev/null +++ b/test_programs/execution_success/bit_not/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bit_not" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/execution_success/bit_not/Prover.toml b/test_programs/execution_success/bit_not/Prover.toml new file mode 100644 index 00000000000..b4bcbcec177 --- /dev/null +++ b/test_programs/execution_success/bit_not/Prover.toml @@ -0,0 +1 @@ +four_as_u32 = 4 diff --git a/test_programs/execution_success/bit_not/src/main.nr b/test_programs/execution_success/bit_not/src/main.nr new file mode 100644 index 00000000000..30b78d330ce --- /dev/null +++ b/test_programs/execution_success/bit_not/src/main.nr @@ -0,0 +1,8 @@ +fn main(four_as_u32: u32) { + let four_as_u8: u8 = 4; + let not_four_as_u8: u8 = !four_as_u8; + assert_eq(not_four_as_u8, 251); + + let not_four_as_u32: u32 = !four_as_u32; + assert_eq(not_four_as_u32, 4294967291); +} diff --git a/test_programs/execution_success/bit_shifts_comptime/Nargo.toml b/test_programs/execution_success/bit_shifts_comptime/Nargo.toml new file mode 100644 index 00000000000..81272be4e98 --- /dev/null +++ b/test_programs/execution_success/bit_shifts_comptime/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "bit_shifts_comptime" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/bit_shifts_comptime/Prover.toml b/test_programs/execution_success/bit_shifts_comptime/Prover.toml new file mode 100644 index 00000000000..cfd62c406cb --- /dev/null +++ b/test_programs/execution_success/bit_shifts_comptime/Prover.toml @@ -0,0 +1 @@ +x = 64 diff --git a/test_programs/execution_success/bit_shifts_comptime/src/main.nr b/test_programs/execution_success/bit_shifts_comptime/src/main.nr new file mode 100644 index 00000000000..a11dae1c716 --- /dev/null +++ b/test_programs/execution_success/bit_shifts_comptime/src/main.nr @@ -0,0 +1,30 @@ +fn main(x: u64) { + let two: u64 = 2; + let three: u64 = 3; + // shifts on constant values + assert(two << 2 == 8); + assert((two << 3) / 8 == two); + assert((three >> 1) == 1); + // shifts on runtime values + assert(x << 1 == 128); + assert(x >> 2 == 16); + + regression_2250(); + + //regression for 3481 + assert(x << 63 == 0); + + assert_eq((1 as u64) << 32, 0x0100000000); + + //regression for 6201 + let a: i16 = -769; + assert_eq(a >> 3, -97); +} + +fn regression_2250() { + let a: u1 = 1 >> 1; + assert(a == 0); + + let b: u32 = 1 >> 32; + assert(b == 0); +} diff --git a/test_programs/execution_success/bit_shifts_runtime/Nargo.toml b/test_programs/execution_success/bit_shifts_runtime/Nargo.toml new file mode 100644 index 00000000000..f60c7dbe658 --- /dev/null +++ b/test_programs/execution_success/bit_shifts_runtime/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "bit_shifts_runtime" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/bit_shifts_runtime/Prover.toml b/test_programs/execution_success/bit_shifts_runtime/Prover.toml new file mode 100644 index 00000000000..7b56d36c9d5 --- /dev/null +++ b/test_programs/execution_success/bit_shifts_runtime/Prover.toml @@ -0,0 +1,3 @@ +x = 64 +y = 1 +z = "-769" diff --git a/test_programs/execution_success/bit_shifts_runtime/src/main.nr b/test_programs/execution_success/bit_shifts_runtime/src/main.nr new file mode 100644 index 00000000000..370bb699048 --- /dev/null +++ b/test_programs/execution_success/bit_shifts_runtime/src/main.nr @@ -0,0 +1,22 @@ +fn main(x: u64, y: u8, z: i16) { + // 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 >> y == 32); + a = -a; + assert(a << 7 == -128); + assert(a << y == -2); + + assert(x >> (x as u8) == 0); + + assert_eq(z >> 3, -97); +} diff --git a/test_programs/execution_success/blake3/Nargo.toml b/test_programs/execution_success/blake3/Nargo.toml new file mode 100644 index 00000000000..29f6ad5f11c --- /dev/null +++ b/test_programs/execution_success/blake3/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "blake3" +type = "bin" +authors = [""] +compiler_version = ">=0.22.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/blake3/Prover.toml b/test_programs/execution_success/blake3/Prover.toml new file mode 100644 index 00000000000..c807701479b --- /dev/null +++ b/test_programs/execution_success/blake3/Prover.toml @@ -0,0 +1,37 @@ +# hello as bytes +# https://connor4312.github.io/blake3/index.html +x = [104, 101, 108, 108, 111] +result = [ + 0xea, + 0x8f, + 0x16, + 0x3d, + 0xb3, + 0x86, + 0x82, + 0x92, + 0x5e, + 0x44, + 0x91, + 0xc5, + 0xe5, + 0x8d, + 0x4b, + 0xb3, + 0x50, + 0x6e, + 0xf8, + 0xc1, + 0x4e, + 0xb7, + 0x8a, + 0x86, + 0xe9, + 0x08, + 0xc5, + 0x62, + 0x4a, + 0x67, + 0x20, + 0x0f, +] diff --git a/test_programs/execution_success/blake3/src/main.nr b/test_programs/execution_success/blake3/src/main.nr new file mode 100644 index 00000000000..fb056bfa848 --- /dev/null +++ b/test_programs/execution_success/blake3/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: [u8; 5], result: [u8; 32]) { + let digest = std::hash::blake3(x); + assert(digest == result); +} diff --git a/test_programs/execution_success/bool_not/Nargo.toml b/test_programs/execution_success/bool_not/Nargo.toml new file mode 100644 index 00000000000..fe42e1efa11 --- /dev/null +++ b/test_programs/execution_success/bool_not/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "bool_not" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/bool_not/Prover.toml b/test_programs/execution_success/bool_not/Prover.toml new file mode 100644 index 00000000000..4dd6b405159 --- /dev/null +++ b/test_programs/execution_success/bool_not/Prover.toml @@ -0,0 +1 @@ +x = "1" diff --git a/test_programs/execution_success/bool_not/src/main.nr b/test_programs/execution_success/bool_not/src/main.nr new file mode 100644 index 00000000000..935d8cc074d --- /dev/null +++ b/test_programs/execution_success/bool_not/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: u1) { + assert(!x == 0); +} + diff --git a/test_programs/execution_success/bool_or/Nargo.toml b/test_programs/execution_success/bool_or/Nargo.toml new file mode 100644 index 00000000000..e139a7a2947 --- /dev/null +++ b/test_programs/execution_success/bool_or/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "bool_or" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/bool_or/Prover.toml b/test_programs/execution_success/bool_or/Prover.toml new file mode 100644 index 00000000000..a0397e89477 --- /dev/null +++ b/test_programs/execution_success/bool_or/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "0" diff --git a/test_programs/execution_success/bool_or/src/main.nr b/test_programs/execution_success/bool_or/src/main.nr new file mode 100644 index 00000000000..6cb959e61e6 --- /dev/null +++ b/test_programs/execution_success/bool_or/src/main.nr @@ -0,0 +1,6 @@ +fn main(x: u1, y: u1) { + assert(x | y == 1); + + assert(x | y | x == 1); +} + 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_acir_as_brillig/Nargo.toml b/test_programs/execution_success/brillig_acir_as_brillig/Nargo.toml new file mode 100644 index 00000000000..aef4fd56d4f --- /dev/null +++ b/test_programs/execution_success/brillig_acir_as_brillig/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_acir_as_brillig" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_acir_as_brillig/Prover.toml b/test_programs/execution_success/brillig_acir_as_brillig/Prover.toml new file mode 100644 index 00000000000..11497a473bc --- /dev/null +++ b/test_programs/execution_success/brillig_acir_as_brillig/Prover.toml @@ -0,0 +1 @@ +x = "0" diff --git a/test_programs/execution_success/brillig_acir_as_brillig/src/main.nr b/test_programs/execution_success/brillig_acir_as_brillig/src/main.nr new file mode 100644 index 00000000000..a327dfd7533 --- /dev/null +++ b/test_programs/execution_success/brillig_acir_as_brillig/src/main.nr @@ -0,0 +1,45 @@ +fn main(x: u32) { + /// Safety: testing context + unsafe { + assert(entry_point(x) == 2); + swap_entry_point(x, x + 1); + assert(deep_entry_point(x) == 4); + } +} + +fn inner(x: u32) -> u32 { + x + 1 +} + +unconstrained fn entry_point(x: u32) -> u32 { + inner(x + 1) +} + +fn swap(x: u32, y: u32) -> (u32, u32) { + (y, x) +} + +unconstrained fn swap_entry_point(x: u32, y: u32) { + let swapped = swap(x, y); + assert(swapped.0 == y); + assert(swapped.1 == x); + let swapped_twice = swap(swapped.0, swapped.1); + assert(swapped_twice.0 == x); + assert(swapped_twice.1 == y); +} + +fn level_3(x: u32) -> u32 { + x + 1 +} + +fn level_2(x: u32) -> u32 { + level_3(x + 1) +} + +fn level_1(x: u32) -> u32 { + level_2(x + 1) +} + +unconstrained fn deep_entry_point(x: u32) -> u32 { + level_1(x + 1) +} diff --git a/test_programs/execution_success/brillig_arrays/Nargo.toml b/test_programs/execution_success/brillig_arrays/Nargo.toml new file mode 100644 index 00000000000..a4433e380a9 --- /dev/null +++ b/test_programs/execution_success/brillig_arrays/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_arrays" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_arrays/Prover.toml b/test_programs/execution_success/brillig_arrays/Prover.toml new file mode 100644 index 00000000000..6371ea2b28b --- /dev/null +++ b/test_programs/execution_success/brillig_arrays/Prover.toml @@ -0,0 +1 @@ +x = ["1", "2", "3"] diff --git a/test_programs/execution_success/brillig_arrays/src/main.nr b/test_programs/execution_success/brillig_arrays/src/main.nr new file mode 100644 index 00000000000..f0524842ac6 --- /dev/null +++ b/test_programs/execution_success/brillig_arrays/src/main.nr @@ -0,0 +1,31 @@ +// Tests a very simple program. +// +// The features being tested are array reads and writes +fn main(x: [Field; 3]) { + /// Safety: testing context + unsafe { + read_array(x); + read_write_array(x); + } +} + +unconstrained fn read_array(x: [Field; 3]) { + assert(x[0] == 1); + let y = [1, 5, 27]; + + assert(y[x[0]] == 5); +} + +unconstrained fn read_write_array(x: [Field; 3]) { + let mut y = x; + + y[0] = 5; + + assert(y[0] == 5); + assert(y[1] == 2); + assert(y[2] == 3); + + assert(x[0] == 1); + assert(x[1] == 2); + assert(x[2] == 3); +} diff --git a/test_programs/execution_success/brillig_blake2s/Nargo.toml b/test_programs/execution_success/brillig_blake2s/Nargo.toml new file mode 100644 index 00000000000..a497b6f48cc --- /dev/null +++ b/test_programs/execution_success/brillig_blake2s/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_blake2s" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_blake2s/Prover.toml b/test_programs/execution_success/brillig_blake2s/Prover.toml new file mode 100644 index 00000000000..8f95d95505f --- /dev/null +++ b/test_programs/execution_success/brillig_blake2s/Prover.toml @@ -0,0 +1,35 @@ +x = [104, 101, 108, 108, 111] +result = [ + 0x19, + 0x21, + 0x3b, + 0xac, + 0xc5, + 0x8d, + 0xee, + 0x6d, + 0xbd, + 0xe3, + 0xce, + 0xb9, + 0xa4, + 0x7c, + 0xbb, + 0x33, + 0x0b, + 0x3d, + 0x86, + 0xf8, + 0xcc, + 0xa8, + 0x99, + 0x7e, + 0xb0, + 0x0b, + 0xe4, + 0x56, + 0xf1, + 0x40, + 0xca, + 0x25, +] diff --git a/test_programs/execution_success/brillig_blake2s/src/main.nr b/test_programs/execution_success/brillig_blake2s/src/main.nr new file mode 100644 index 00000000000..7e567b84139 --- /dev/null +++ b/test_programs/execution_success/brillig_blake2s/src/main.nr @@ -0,0 +1,13 @@ +// Tests a very simple program. +// +// The features being tested is blake2s in brillig +fn main(x: [u8; 5], result: [u8; 32]) { + /// Safety: testing context + unsafe { + assert(blake2s(x) == result); + } +} + +unconstrained fn blake2s(x: [u8; 5]) -> [u8; 32] { + std::hash::blake2s(x) +} 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..7f04dcd4d04 --- /dev/null +++ b/test_programs/execution_success/brillig_block_parameter_liveness/src/main.nr @@ -0,0 +1,90 @@ +// 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 = std::mem::zeroed(); + outer.middle_a.inner_a.a = 1; + outer + } else { + let mut outer: Outer = std::mem::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_calls/Nargo.toml b/test_programs/execution_success/brillig_calls/Nargo.toml new file mode 100644 index 00000000000..7cc53a33a8a --- /dev/null +++ b/test_programs/execution_success/brillig_calls/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_calls" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_calls/Prover.toml b/test_programs/execution_success/brillig_calls/Prover.toml new file mode 100644 index 00000000000..11497a473bc --- /dev/null +++ b/test_programs/execution_success/brillig_calls/Prover.toml @@ -0,0 +1 @@ +x = "0" diff --git a/test_programs/execution_success/brillig_calls/src/main.nr b/test_programs/execution_success/brillig_calls/src/main.nr new file mode 100644 index 00000000000..5bd3458da51 --- /dev/null +++ b/test_programs/execution_success/brillig_calls/src/main.nr @@ -0,0 +1,61 @@ +// Tests a very simple program. +// +// The features being tested is brillig calls +fn main(x: u32) { + unsafe { + /*@safety : testing context*/ + assert(entry_point(x) == 2); + swap_entry_point(x, x + 1); + assert(deep_entry_point(x) == 4); + multiple_values_entry_point(x); + } +} + +unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { + (x + 1, x + 2, x + 3, x + 4) +} + +unconstrained fn multiple_values_entry_point(x: u32) { + let (a, b, c, d) = returns_multiple_values(x); + assert(a == x + 1); + assert(b == x + 2); + assert(c == x + 3); + assert(d == x + 4); +} + +unconstrained fn inner(x: u32) -> u32 { + x + 1 +} + +unconstrained fn entry_point(x: u32) -> u32 { + inner(x + 1) +} + +unconstrained fn swap(x: u32, y: u32) -> (u32, u32) { + (y, x) +} + +unconstrained fn swap_entry_point(x: u32, y: u32) { + let swapped = swap(x, y); + assert(swapped.0 == y); + assert(swapped.1 == x); + let swapped_twice = swap(swapped.0, swapped.1); + assert(swapped_twice.0 == x); + assert(swapped_twice.1 == y); +} + +unconstrained fn level_3(x: u32) -> u32 { + x + 1 +} + +unconstrained fn level_2(x: u32) -> u32 { + level_3(x + 1) +} + +unconstrained fn level_1(x: u32) -> u32 { + level_2(x + 1) +} + +unconstrained fn deep_entry_point(x: u32) -> u32 { + level_1(x + 1) +} diff --git a/test_programs/execution_success/brillig_calls_array/Nargo.toml b/test_programs/execution_success/brillig_calls_array/Nargo.toml new file mode 100644 index 00000000000..e360f2d6338 --- /dev/null +++ b/test_programs/execution_success/brillig_calls_array/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_calls_array" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_calls_array/Prover.toml b/test_programs/execution_success/brillig_calls_array/Prover.toml new file mode 100644 index 00000000000..99580ca45bc --- /dev/null +++ b/test_programs/execution_success/brillig_calls_array/Prover.toml @@ -0,0 +1 @@ +x = ["1","2","3"] diff --git a/test_programs/execution_success/brillig_calls_array/src/main.nr b/test_programs/execution_success/brillig_calls_array/src/main.nr new file mode 100644 index 00000000000..b27eb30da17 --- /dev/null +++ b/test_programs/execution_success/brillig_calls_array/src/main.nr @@ -0,0 +1,36 @@ +// Tests a very simple program. +// +// The features being tested is brillig calls passing arrays around +fn main(x: [u32; 3]) { + /// Safety: testing context + unsafe { + assert(entry_point(x) == 9); + another_entry_point(x); + } +} + +unconstrained fn inner(x: [u32; 3]) -> [u32; 3] { + [x[0] + 1, x[1] + 1, x[2] + 1] +} + +unconstrained fn entry_point(x: [u32; 3]) -> u32 { + let y = inner(x); + y[0] + y[1] + y[2] +} + +unconstrained fn nested_fn_that_allocates(value: u32) -> u32 { + let x = [value, value, value]; + let y = inner(x); + y[0] + y[1] + y[2] +} + +unconstrained fn another_entry_point(x: [u32; 3]) { + assert(x[0] == 1); + assert(x[1] == 2); + assert(x[2] == 3); + assert(nested_fn_that_allocates(1) == 6); + // x should be unchanged + assert(x[0] == 1); + assert(x[1] == 2); + assert(x[2] == 3); +} diff --git a/test_programs/execution_success/brillig_calls_conditionals/Nargo.toml b/test_programs/execution_success/brillig_calls_conditionals/Nargo.toml new file mode 100644 index 00000000000..1553cd525ff --- /dev/null +++ b/test_programs/execution_success/brillig_calls_conditionals/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_calls_conditionals" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_calls_conditionals/Prover.toml b/test_programs/execution_success/brillig_calls_conditionals/Prover.toml new file mode 100644 index 00000000000..99580ca45bc --- /dev/null +++ b/test_programs/execution_success/brillig_calls_conditionals/Prover.toml @@ -0,0 +1 @@ +x = ["1","2","3"] diff --git a/test_programs/execution_success/brillig_calls_conditionals/src/main.nr b/test_programs/execution_success/brillig_calls_conditionals/src/main.nr new file mode 100644 index 00000000000..31b70cb12cf --- /dev/null +++ b/test_programs/execution_success/brillig_calls_conditionals/src/main.nr @@ -0,0 +1,39 @@ +// Tests a very simple program. +// +// The features being tested is brillig calls with conditionals +fn main(x: [u32; 3]) { + /// Safety: testing context + unsafe { + assert(entry_point(x[0]) == 7); + assert(entry_point(x[1]) == 8); + assert(entry_point(x[2]) == 9); + assert(entry_point(42) == 0); + } +} + +unconstrained fn inner_1() -> u32 { + 7 +} + +unconstrained fn inner_2() -> u32 { + 8 +} + +unconstrained fn inner_3() -> u32 { + 9 +} + +unconstrained fn entry_point(x: u32) -> u32 { + let mut result: u32 = 0; + + if x == 1 { + result = inner_1(); + } else if x == 2 { + result = inner_2(); + } else if x == 3 { + result = inner_3(); + } + + result +} + diff --git a/test_programs/execution_success/brillig_conditional/Nargo.toml b/test_programs/execution_success/brillig_conditional/Nargo.toml new file mode 100644 index 00000000000..6a8be620fee --- /dev/null +++ b/test_programs/execution_success/brillig_conditional/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_conditional" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_conditional/Prover.toml b/test_programs/execution_success/brillig_conditional/Prover.toml new file mode 100644 index 00000000000..4dd6b405159 --- /dev/null +++ b/test_programs/execution_success/brillig_conditional/Prover.toml @@ -0,0 +1 @@ +x = "1" diff --git a/test_programs/execution_success/brillig_conditional/src/main.nr b/test_programs/execution_success/brillig_conditional/src/main.nr new file mode 100644 index 00000000000..024ee52d5af --- /dev/null +++ b/test_programs/execution_success/brillig_conditional/src/main.nr @@ -0,0 +1,17 @@ +// Tests a very simple program. +// +// The features being tested is basic conditonal on brillig +fn main(x: Field) { + /// Safety: testing context + unsafe { + assert(4 == conditional(x == 1)); + } +} + +unconstrained fn conditional(x: bool) -> Field { + if x { + 4 + } else { + 5 + } +} diff --git a/test_programs/execution_success/brillig_constant_reference_regression/Nargo.toml b/test_programs/execution_success/brillig_constant_reference_regression/Nargo.toml new file mode 100644 index 00000000000..2df127c83e8 --- /dev/null +++ b/test_programs/execution_success/brillig_constant_reference_regression/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_constant_reference_regression" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_constant_reference_regression/Prover.toml b/test_programs/execution_success/brillig_constant_reference_regression/Prover.toml new file mode 100644 index 00000000000..8fbe88fbb98 --- /dev/null +++ b/test_programs/execution_success/brillig_constant_reference_regression/Prover.toml @@ -0,0 +1 @@ +sorted_index = ["1", "0"] diff --git a/test_programs/execution_success/brillig_constant_reference_regression/src/main.nr b/test_programs/execution_success/brillig_constant_reference_regression/src/main.nr new file mode 100644 index 00000000000..67bde87c712 --- /dev/null +++ b/test_programs/execution_success/brillig_constant_reference_regression/src/main.nr @@ -0,0 +1,12 @@ +unconstrained fn main(sorted_index: [u32; 2]) { + let original = [55, 11]; + + let mut sorted = original; // Stores the constant "original" into the sorted reference + for i in 0..2 { + let index = sorted_index[i]; + let value = original[index]; + sorted[i] = value; // On first iteration, we should not mutate the original constant array, RC should be > 1 + } + + assert_eq(sorted[1], 55); +} diff --git a/test_programs/execution_success/brillig_cow/Nargo.toml b/test_programs/execution_success/brillig_cow/Nargo.toml new file mode 100644 index 00000000000..d191eb53ddf --- /dev/null +++ b/test_programs/execution_success/brillig_cow/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_cow" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_cow/Prover.toml b/test_programs/execution_success/brillig_cow/Prover.toml new file mode 100644 index 00000000000..6533d218b15 --- /dev/null +++ b/test_programs/execution_success/brillig_cow/Prover.toml @@ -0,0 +1,7 @@ +original = [0, 1, 2, 3, 4] +index = 2 + +[expected_result] +original = [0, 1, 2, 3, 4] +modified_once = [0, 1, 27, 3, 4] +modified_twice = [0, 1, 27, 27, 4] diff --git a/test_programs/execution_success/brillig_cow/src/main.nr b/test_programs/execution_success/brillig_cow/src/main.nr new file mode 100644 index 00000000000..2dd0d4b3411 --- /dev/null +++ b/test_programs/execution_success/brillig_cow/src/main.nr @@ -0,0 +1,48 @@ +// Tests the copy on write optimization for arrays. We look for cases where we are modifying an array in place when we shouldn't. +global ARRAY_SIZE: u32 = 5; + +struct ExecutionResult { + original: [Field; ARRAY_SIZE], + modified_once: [Field; ARRAY_SIZE], + modified_twice: [Field; ARRAY_SIZE], +} + +impl ExecutionResult { + fn is_equal(self, other: ExecutionResult) -> bool { + (self.original == other.original) + & (self.modified_once == other.modified_once) + & (self.modified_twice == other.modified_twice) + } +} + +fn modify_in_inlined_constrained(original: [Field; ARRAY_SIZE], index: u64) -> ExecutionResult { + let mut modified = original; + + modified[index] = 27; + + let modified_once = modified; + + modified[index + 1] = 27; + + ExecutionResult { original, modified_once, modified_twice: modified } +} + +unconstrained fn modify_in_unconstrained( + original: [Field; ARRAY_SIZE], + index: u64, +) -> ExecutionResult { + let mut modified = original; + + modified[index] = 27; + + let modified_once = modified; + + modified[index + 1] = 27; + + ExecutionResult { original, modified_once, modified_twice: modified } +} + +unconstrained fn main(original: [Field; ARRAY_SIZE], index: u64, expected_result: ExecutionResult) { + assert(expected_result.is_equal(modify_in_unconstrained(original, index))); + assert(expected_result.is_equal(modify_in_inlined_constrained(original, index))); +} diff --git a/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..cfa228b3a96 --- /dev/null +++ b/test_programs/execution_success/brillig_cow_assign/src/main.nr @@ -0,0 +1,22 @@ +global N: u32 = 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/Nargo.toml b/test_programs/execution_success/brillig_cow_regression/Nargo.toml new file mode 100644 index 00000000000..c5bf60a1e78 --- /dev/null +++ b/test_programs/execution_success/brillig_cow_regression/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_cow_regression" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_cow_regression/Prover.toml b/test_programs/execution_success/brillig_cow_regression/Prover.toml new file mode 100644 index 00000000000..44813823448 --- /dev/null +++ b/test_programs/execution_success/brillig_cow_regression/Prover.toml @@ -0,0 +1,229 @@ +[kernel_data] +encrypted_logs_hash = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", +] +new_note_hashes = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", +] +new_l2_to_l1_msgs = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", +] +new_nullifiers = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", +] +unencrypted_logs_hash = [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", +] + +[[kernel_data.new_contracts]] +contract_address = "0x0000000000000000000000000000000000000000000000000000000000000000" +portal_contract_address = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" + +[[kernel_data.public_data_update_requests]] +leaf_slot = "0x0000000000000000000000000000000000000000000000000000000000000000" +new_value = "0x0000000000000000000000000000000000000000000000000000000000000000" +old_value = "0x0000000000000000000000000000000000000000000000000000000000000000" diff --git a/test_programs/execution_success/brillig_cow_regression/src/main.nr b/test_programs/execution_success/brillig_cow_regression/src/main.nr new file mode 100644 index 00000000000..69273bc3dca --- /dev/null +++ b/test_programs/execution_success/brillig_cow_regression/src/main.nr @@ -0,0 +1,177 @@ +// Tests a performance regression found in aztec-packages with brillig cow optimization +global MAX_NOTE_HASHES_PER_TX: u32 = 64; +global MAX_NULLIFIERS_PER_TX: u32 = 64; +global MAX_L2_TO_L1_MSGS_PER_TX: u32 = 2; +global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u32 = 16; +global MAX_NEW_CONTRACTS_PER_TX: u32 = 1; +global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u32 = 1; +global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: u32 = 1; +global NUM_FIELDS_PER_SHA256: u32 = 2; +global TX_EFFECT_HASH_INPUT_SIZE: u32 = 169; +global TX_EFFECT_HASH_LOG_FIELDS: u32 = 4; +global TX_EFFECT_HASH_FULL_FIELDS: u32 = 165; + +struct PublicDataUpdateRequest { + leaf_slot: Field, + old_value: Field, + new_value: Field, +} + +struct NewContractData { + contract_address: Field, + portal_contract_address: Field, +} + +impl NewContractData { + fn hash(self) -> Field { + std::hash::pedersen_hash([self.contract_address, self.portal_contract_address]) + } +} + +struct DataToHash { + new_note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + new_nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + new_l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX], + encrypted_logs_hash: [Field; NUM_FIELDS_PER_SHA256], + unencrypted_logs_hash: [Field; NUM_FIELDS_PER_SHA256], + new_contracts: [NewContractData; MAX_NEW_CONTRACTS_PER_TX], +} + +struct U256 { + // This is in big-endian order, typically because + // sha256 is usually in big endian order. + // Note: this means that inner[0] has the most significant 64 bits. + inner: [u64; 4], +} + +impl U256 { + pub fn from_bytes32(bytes: [u8; 32]) -> U256 { + // We use addition rather than a bitwise OR as the bitshifts ensure that none of the bytes overlap each other. + let high_0 = ((bytes[0] as u64) << 56) + + ((bytes[1] as u64) << 48) + + ((bytes[2] as u64) << 40) + + ((bytes[3] as u64) << 32) + + ((bytes[4] as u64) << 24) + + ((bytes[5] as u64) << 16) + + ((bytes[6] as u64) << 8) + + (bytes[7] as u64); + + let high_1 = ((bytes[8] as u64) << 56) + + ((bytes[9] as u64) << 48) + + ((bytes[10] as u64) << 40) + + ((bytes[11] as u64) << 32) + + ((bytes[12] as u64) << 24) + + ((bytes[13] as u64) << 16) + + ((bytes[14] as u64) << 8) + + (bytes[15] as u64); + + let low_0 = ((bytes[16] as u64) << 56) + + ((bytes[17] as u64) << 48) + + ((bytes[18] as u64) << 40) + + ((bytes[19] as u64) << 32) + + ((bytes[20] as u64) << 24) + + ((bytes[21] as u64) << 16) + + ((bytes[22] as u64) << 8) + + (bytes[23] as u64); + + let low_1 = ((bytes[24] as u64) << 56) + + ((bytes[25] as u64) << 48) + + ((bytes[26] as u64) << 40) + + ((bytes[27] as u64) << 32) + + ((bytes[28] as u64) << 24) + + ((bytes[29] as u64) << 16) + + ((bytes[30] as u64) << 8) + + (bytes[31] as u64); + + U256 { inner: [high_0, high_1, low_0, low_1] } + } + + pub fn to_u128_limbs(self) -> [Field; 2] { + let two_pow_64 = 2.pow_32(64); + + let high = (self.inner[0] as Field) * two_pow_64 + self.inner[1] as Field; + let low = (self.inner[2] as Field) * two_pow_64 + self.inner[3] as Field; + + [high, low] + } +} + +unconstrained fn main(kernel_data: DataToHash) -> pub [Field; NUM_FIELDS_PER_SHA256] { + 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; + let public_data_update_requests = kernel_data.public_data_update_requests; + let l2ToL1Msgs = kernel_data.new_l2_to_l1_msgs; + let encryptedLogsHash = kernel_data.encrypted_logs_hash; + let unencryptedLogsHash = kernel_data.unencrypted_logs_hash; + + let mut offset = 0; + + for j in 0..MAX_NOTE_HASHES_PER_TX { + tx_effects_hash_inputs[offset + j] = new_note_hashes[j]; + } + offset += MAX_NOTE_HASHES_PER_TX; + + for j in 0..MAX_NULLIFIERS_PER_TX { + tx_effects_hash_inputs[offset + j] = new_nullifiers[j]; + } + offset += MAX_NULLIFIERS_PER_TX; + + for j in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { + tx_effects_hash_inputs[offset + j * 2] = public_data_update_requests[j].leaf_slot; + 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_L2_TO_L1_MSGS_PER_TX { + tx_effects_hash_inputs[offset + j] = l2ToL1Msgs[j]; + } + offset += MAX_L2_TO_L1_MSGS_PER_TX; + + let contract_leaf = kernel_data.new_contracts[0]; + tx_effects_hash_inputs[offset] = contract_leaf.hash(); + + offset += MAX_NEW_CONTRACTS_PER_TX; + + let new_contracts = kernel_data.new_contracts; + tx_effects_hash_inputs[offset] = new_contracts[0].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 { + 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 { + tx_effects_hash_inputs[offset + j] = unencryptedLogsHash[j]; + } + + offset += NUM_UNENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256; + assert_eq(offset, TX_EFFECT_HASH_INPUT_SIZE); // Sanity check + 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: [u8; 32] = tx_effects_hash_inputs[offset].to_be_bytes(); + for byte_index in 0..32 { + hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index]; + } + } + + for log_field_index in 0..TX_EFFECT_HASH_LOG_FIELDS { + let input_as_bytes: [u8; 16] = + tx_effects_hash_inputs[TX_EFFECT_HASH_FULL_FIELDS + log_field_index].to_be_bytes(); + for byte_index in 0..16 { + hash_input_flattened[TX_EFFECT_HASH_FULL_FIELDS * 32 + log_field_index * 16 + byte_index] = + input_as_bytes[byte_index]; + } + } + + let sha_digest = std::hash::sha256(hash_input_flattened); + U256::from_bytes32(sha_digest).to_u128_limbs() +} diff --git a/test_programs/execution_success/brillig_fns_as_values/Nargo.toml b/test_programs/execution_success/brillig_fns_as_values/Nargo.toml new file mode 100644 index 00000000000..decd9a9412a --- /dev/null +++ b/test_programs/execution_success/brillig_fns_as_values/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_fns_as_values" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_fns_as_values/Prover.toml b/test_programs/execution_success/brillig_fns_as_values/Prover.toml new file mode 100644 index 00000000000..4dd6b405159 --- /dev/null +++ b/test_programs/execution_success/brillig_fns_as_values/Prover.toml @@ -0,0 +1 @@ +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 new file mode 100644 index 00000000000..ff1c36c9ddf --- /dev/null +++ b/test_programs/execution_success/brillig_fns_as_values/src/main.nr @@ -0,0 +1,37 @@ +struct MyStruct { + operation: unconstrained fn(u32) -> u32, +} + +fn main(x: u32) { + /// Safety: testing context + unsafe { + assert(wrapper(increment, x) == x + 1); + assert(wrapper(increment_acir, x) == 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) == x - 1); + // https://github.com/noir-lang/noir/issues/1975 + assert(increment(x) == x + 1); + } +} + +unconstrained fn wrapper(func: unconstrained fn(u32) -> u32, param: u32) -> u32 { + func(param) +} + +unconstrained fn increment(x: u32) -> u32 { + x + 1 +} + +unconstrained fn decrement(x: u32) -> u32 { + x - 1 +} + +unconstrained fn wrapper_with_struct(my_struct: MyStruct, param: u32) -> u32 { + let func = my_struct.operation; + func(param) +} + +fn increment_acir(x: u32) -> u32 { + x + 1 +} diff --git a/test_programs/execution_success/brillig_identity_function/Nargo.toml b/test_programs/execution_success/brillig_identity_function/Nargo.toml new file mode 100644 index 00000000000..8196884fe2b --- /dev/null +++ b/test_programs/execution_success/brillig_identity_function/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_identity_function" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_identity_function/Prover.toml b/test_programs/execution_success/brillig_identity_function/Prover.toml new file mode 100644 index 00000000000..55cccb955a9 --- /dev/null +++ b/test_programs/execution_success/brillig_identity_function/Prover.toml @@ -0,0 +1,2 @@ +x = "3" + diff --git a/test_programs/execution_success/brillig_identity_function/src/main.nr b/test_programs/execution_success/brillig_identity_function/src/main.nr new file mode 100644 index 00000000000..b676c46120e --- /dev/null +++ b/test_programs/execution_success/brillig_identity_function/src/main.nr @@ -0,0 +1,35 @@ +struct myStruct { + foo: Field, + foo_arr: [Field; 2], +} +// Tests a very simple program. +// +// The features being tested is the identity function in Brillig +fn main(x: Field) { + /// Safety: testing context + unsafe { + assert(x == identity(x)); + // TODO: add support for array comparison + let arr = identity_array([x, x]); + assert(x == arr[0]); + assert(x == arr[1]); + + let s = myStruct { foo: x, foo_arr: [x, x] }; + let identity_struct = identity_struct(s); + assert(x == identity_struct.foo); + assert(x == identity_struct.foo_arr[0]); + assert(x == identity_struct.foo_arr[1]); + } +} + +unconstrained fn identity(x: Field) -> Field { + x +} + +unconstrained fn identity_array(arr: [Field; 2]) -> [Field; 2] { + arr +} + +unconstrained fn identity_struct(s: myStruct) -> myStruct { + s +} diff --git a/test_programs/execution_success/brillig_loop_size_regression/Nargo.toml b/test_programs/execution_success/brillig_loop_size_regression/Nargo.toml new file mode 100644 index 00000000000..d2a98e19742 --- /dev/null +++ b/test_programs/execution_success/brillig_loop_size_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_loop_size_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/brillig_loop_size_regression/Prover.toml b/test_programs/execution_success/brillig_loop_size_regression/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/execution_success/brillig_loop_size_regression/src/main.nr b/test_programs/execution_success/brillig_loop_size_regression/src/main.nr new file mode 100644 index 00000000000..88c6544dcaa --- /dev/null +++ b/test_programs/execution_success/brillig_loop_size_regression/src/main.nr @@ -0,0 +1,17 @@ +struct EnumEmulation { + a: Option, + b: Option, + c: Option, +} + +unconstrained fn main() -> pub Field { + let mut emulated_enum = + EnumEmulation { a: Option::some(1), b: Option::none(), c: Option::none() }; + + for _ in 0..1 { + assert_eq(emulated_enum.a.unwrap(), 1); + } + + emulated_enum.a = Option::some(2); + emulated_enum.a.unwrap() +} diff --git a/test_programs/execution_success/brillig_nested_arrays/Nargo.toml b/test_programs/execution_success/brillig_nested_arrays/Nargo.toml new file mode 100644 index 00000000000..c36c8a0a2bd --- /dev/null +++ b/test_programs/execution_success/brillig_nested_arrays/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "brillig_nested_arrays" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/brillig_nested_arrays/Prover.toml b/test_programs/execution_success/brillig_nested_arrays/Prover.toml new file mode 100644 index 00000000000..26fdbc19975 --- /dev/null +++ b/test_programs/execution_success/brillig_nested_arrays/Prover.toml @@ -0,0 +1,2 @@ +x = "0" +y = "1" diff --git a/test_programs/execution_success/brillig_nested_arrays/src/main.nr b/test_programs/execution_success/brillig_nested_arrays/src/main.nr new file mode 100644 index 00000000000..feb5433738f --- /dev/null +++ b/test_programs/execution_success/brillig_nested_arrays/src/main.nr @@ -0,0 +1,44 @@ +struct Header { + params: [Field; 3], +} + +struct MyNote { + plain: Field, + array: [Field; 2], + header: Header, +} + +unconstrained fn access_nested(notes: [MyNote; 2], x: Field, y: Field) -> Field { + notes[x].array[y] + notes[y].array[x] + notes[x].plain + notes[y].header.params[x] +} + +unconstrained fn create_inside_brillig() -> [MyNote; 2] { + let header = Header { params: [1, 2, 3] }; + let note0 = MyNote { array: [1, 2], plain: 3, header }; + let note1 = MyNote { array: [4, 5], plain: 6, header }; + [note0, note1] +} + +unconstrained fn assert_inside_brillig(notes: [MyNote; 2], x: Field, y: Field) { + assert(access_nested(notes, x, y) == (2 + 4 + 3 + 1)); +} + +unconstrained fn create_and_assert_inside_brillig(x: Field, y: Field) { + assert_inside_brillig(create_inside_brillig(), x, y); +} + +fn main(x: Field, y: Field) { + /// Safety: testing context + unsafe { + let header = Header { params: [1, 2, 3] }; + let note0 = MyNote { array: [1, 2], plain: 3, header }; + let note1 = MyNote { array: [4, 5], plain: 6, header }; + + assert(access_nested([note0, note1], x, y) == (2 + 4 + 3 + 1)); + + let notes = create_inside_brillig(); + assert_inside_brillig(notes, x, y); + create_and_assert_inside_brillig(x, y); + } +} + diff --git a/test_programs/execution_success/brillig_not/Nargo.toml b/test_programs/execution_success/brillig_not/Nargo.toml new file mode 100644 index 00000000000..ef882ea8da0 --- /dev/null +++ b/test_programs/execution_success/brillig_not/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_not" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_not/Prover.toml b/test_programs/execution_success/brillig_not/Prover.toml new file mode 100644 index 00000000000..a0397e89477 --- /dev/null +++ b/test_programs/execution_success/brillig_not/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "0" diff --git a/test_programs/execution_success/brillig_not/src/main.nr b/test_programs/execution_success/brillig_not/src/main.nr new file mode 100644 index 00000000000..6dc91f86127 --- /dev/null +++ b/test_programs/execution_success/brillig_not/src/main.nr @@ -0,0 +1,14 @@ +// Tests a very simple Brillig function. +// +// The features being tested is not instruction on brillig +fn main(x: Field, y: Field) { + /// Safety: testing context + unsafe { + assert(false == not_operator(x as bool)); + assert(true == not_operator(y as bool)); + } +} + +unconstrained fn not_operator(x: bool) -> bool { + !x +} diff --git a/test_programs/execution_success/brillig_pedersen/Nargo.toml b/test_programs/execution_success/brillig_pedersen/Nargo.toml new file mode 100644 index 00000000000..6327caa0a09 --- /dev/null +++ b/test_programs/execution_success/brillig_pedersen/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_pedersen" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_pedersen/Prover.toml b/test_programs/execution_success/brillig_pedersen/Prover.toml new file mode 100644 index 00000000000..db1ebdf6c51 --- /dev/null +++ b/test_programs/execution_success/brillig_pedersen/Prover.toml @@ -0,0 +1,7 @@ +x = "0" +y = "1" +salt = "42" + +out_x = "0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402" +out_y = "0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126" +out_hash = "0x0d98561fb02ca04d00801dfdc118b2a24cea0351963587712a28d368041370e1" diff --git a/test_programs/execution_success/brillig_pedersen/src/main.nr b/test_programs/execution_success/brillig_pedersen/src/main.nr new file mode 100644 index 00000000000..55f81882bd4 --- /dev/null +++ b/test_programs/execution_success/brillig_pedersen/src/main.nr @@ -0,0 +1,27 @@ +unconstrained fn main( + x: Field, + y: Field, + salt: Field, + out_x: Field, + out_y: Field, + out_hash: Field, +) { + let res = std::hash::pedersen_commitment_with_separator([x, y], 0); + assert(res.x == out_x); + assert(res.y == out_y); + + let res_hash = std::hash::pedersen_hash_with_separator([x, y], 0); + assert_eq(res_hash, out_hash); + + assert(res_hash != res.x); + + let raw_data = [x, y]; + let mut state = 0; + for i in 0..(2 as u32) { + state = state * 8 + raw_data[i]; + } + state += salt; + let hash = std::hash::pedersen_commitment_with_separator([state], 0); + assert(std::hash::pedersen_commitment_with_separator([43], 0).x == hash.x); +} + diff --git a/test_programs/execution_success/brillig_rc_regression_6123/Nargo.toml b/test_programs/execution_success/brillig_rc_regression_6123/Nargo.toml new file mode 100644 index 00000000000..533777df67f --- /dev/null +++ b/test_programs/execution_success/brillig_rc_regression_6123/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_rc_regression_6123" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/brillig_rc_regression_6123/src/main.nr b/test_programs/execution_success/brillig_rc_regression_6123/src/main.nr new file mode 100644 index 00000000000..3eb29659944 --- /dev/null +++ b/test_programs/execution_success/brillig_rc_regression_6123/src/main.nr @@ -0,0 +1,41 @@ +struct Builder { + note_hashes: BoundedVec, + nullifiers: BoundedVec, +} + +impl Builder { + fn append_note_hashes_with_logs(&mut self, num_note_hashes: u32) { + let index_offset = self.note_hashes.len(); + for i in 0..self.note_hashes.max_len() { + if i < num_note_hashes { + self.add_new_note_hash((index_offset + i) as Field); + } + } + } + + fn add_new_note_hash(&mut self, value: Field) { + self.note_hashes.push(value); + } +} + +fn swap_items(vec: &mut BoundedVec, from_index: u32, to_index: u32) { + let tmp = vec.storage[from_index]; + vec.storage[from_index] = vec.storage[to_index]; + vec.storage[to_index] = tmp; +} + +unconstrained fn main() { + let mut builder = Builder { note_hashes: BoundedVec::new(), nullifiers: BoundedVec::new() }; + + builder.append_note_hashes_with_logs(2); + builder.nullifiers.storage[1] = 27; + // Get ordered items before shuffling. + let note_hashes = builder.note_hashes.storage; + let original_first_note_hash = note_hashes[0]; + // Shuffle. + swap_items(&mut builder.note_hashes, 1, 0); + + for i in 0..1 { + assert_eq(note_hashes[i], original_first_note_hash); + } +} diff --git a/test_programs/execution_success/brillig_recursion/Nargo.toml b/test_programs/execution_success/brillig_recursion/Nargo.toml new file mode 100644 index 00000000000..087eeefd5ac --- /dev/null +++ b/test_programs/execution_success/brillig_recursion/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_recursion" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_recursion/Prover.toml b/test_programs/execution_success/brillig_recursion/Prover.toml new file mode 100644 index 00000000000..3a627b9188b --- /dev/null +++ b/test_programs/execution_success/brillig_recursion/Prover.toml @@ -0,0 +1 @@ +x = "10" diff --git a/test_programs/execution_success/brillig_recursion/src/main.nr b/test_programs/execution_success/brillig_recursion/src/main.nr new file mode 100644 index 00000000000..e7140ffa06c --- /dev/null +++ b/test_programs/execution_success/brillig_recursion/src/main.nr @@ -0,0 +1,17 @@ +// Tests a very simple program. +// +// The feature being tested is brillig recursion +fn main(x: u32) { + /// Safety: testing context + unsafe { + assert(fibonacci(x) == 55); + } +} + +unconstrained fn fibonacci(x: u32) -> u32 { + if x <= 1 { + x + } else { + fibonacci(x - 1) + fibonacci(x - 2) + } +} diff --git a/test_programs/execution_success/brillig_uninitialized_arrays/Nargo.toml b/test_programs/execution_success/brillig_uninitialized_arrays/Nargo.toml new file mode 100644 index 00000000000..68bcf9929cc --- /dev/null +++ b/test_programs/execution_success/brillig_uninitialized_arrays/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_uninitialized_arrays" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_uninitialized_arrays/Prover.toml b/test_programs/execution_success/brillig_uninitialized_arrays/Prover.toml new file mode 100644 index 00000000000..b6626a67e19 --- /dev/null +++ b/test_programs/execution_success/brillig_uninitialized_arrays/Prover.toml @@ -0,0 +1,2 @@ +x = 1 +y = 0 diff --git a/test_programs/execution_success/brillig_uninitialized_arrays/src/main.nr b/test_programs/execution_success/brillig_uninitialized_arrays/src/main.nr new file mode 100644 index 00000000000..39a13440ca9 --- /dev/null +++ b/test_programs/execution_success/brillig_uninitialized_arrays/src/main.nr @@ -0,0 +1,15 @@ +fn main(x: Field, y: Field) -> pub Field { + /// Safety: testing context + unsafe { + let notes = create_notes(x, y); + sum_x(notes, x, y) + } +} + +fn sum_x(notes: [Field; 2], x: Field, y: Field) -> Field { + notes[x] + notes[y] +} + +unconstrained fn create_notes(x: Field, y: Field) -> [Field; 2] { + [x, y] +} diff --git a/test_programs/execution_success/cast_bool/Nargo.toml b/test_programs/execution_success/cast_bool/Nargo.toml new file mode 100644 index 00000000000..6571019494e --- /dev/null +++ b/test_programs/execution_success/cast_bool/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "cast_bool" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/cast_bool/Prover.toml b/test_programs/execution_success/cast_bool/Prover.toml new file mode 100644 index 00000000000..f489cbac003 --- /dev/null +++ b/test_programs/execution_success/cast_bool/Prover.toml @@ -0,0 +1,2 @@ +x = "10" +y = "10" \ No newline at end of file diff --git a/test_programs/execution_success/cast_bool/src/main.nr b/test_programs/execution_success/cast_bool/src/main.nr new file mode 100644 index 00000000000..422d3b98f83 --- /dev/null +++ b/test_programs/execution_success/cast_bool/src/main.nr @@ -0,0 +1,6 @@ +fn main(x: Field, y: Field) { + let z = x == y; + let t = z as u8; + assert(t == 1); +} + diff --git a/test_programs/execution_success/closures_mut_ref/Nargo.toml b/test_programs/execution_success/closures_mut_ref/Nargo.toml new file mode 100644 index 00000000000..01936c7be65 --- /dev/null +++ b/test_programs/execution_success/closures_mut_ref/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "closures_mut_ref" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/closures_mut_ref/Prover.toml b/test_programs/execution_success/closures_mut_ref/Prover.toml new file mode 100644 index 00000000000..11497a473bc --- /dev/null +++ b/test_programs/execution_success/closures_mut_ref/Prover.toml @@ -0,0 +1 @@ +x = "0" diff --git a/test_programs/execution_success/closures_mut_ref/src/main.nr b/test_programs/execution_success/closures_mut_ref/src/main.nr new file mode 100644 index 00000000000..bff2649aead --- /dev/null +++ b/test_programs/execution_success/closures_mut_ref/src/main.nr @@ -0,0 +1,26 @@ +fn main(mut x: Field) { + let one = 1; + let add1 = |z| { *z = *z + one; }; + + let two = 2; + let add2 = |z| { *z = *z + two; }; + + add1(&mut x); + assert(x == 1); + + add2(&mut x); + assert(x == 3); + + issue_2120(); +} +// https://github.com/noir-lang/noir/issues/2120 +fn issue_2120() { + let x1 = &mut 42; + let set_x1 = |y| { *x1 = y; }; + + assert(*x1 == 42); + set_x1(44); + assert(*x1 == 44); + set_x1(*x1); + assert(*x1 == 44); +} diff --git a/test_programs/execution_success/comptime_println/Nargo.toml b/test_programs/execution_success/comptime_println/Nargo.toml new file mode 100644 index 00000000000..7f8ae3a9cb9 --- /dev/null +++ b/test_programs/execution_success/comptime_println/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_println" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] diff --git a/test_programs/execution_success/comptime_println/src/main.nr b/test_programs/execution_success/comptime_println/src/main.nr new file mode 100644 index 00000000000..f9770066c04 --- /dev/null +++ b/test_programs/execution_success/comptime_println/src/main.nr @@ -0,0 +1,7 @@ +fn main() { + let x = comptime { + println("hello from compile-time!"); + 1 + 2 + }; + println(x); +} diff --git a/test_programs/execution_success/conditional_1/Nargo.toml b/test_programs/execution_success/conditional_1/Nargo.toml new file mode 100644 index 00000000000..28ca01332df --- /dev/null +++ b/test_programs/execution_success/conditional_1/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_1" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/conditional_1/Prover.toml b/test_programs/execution_success/conditional_1/Prover.toml new file mode 100644 index 00000000000..baad8be126a --- /dev/null +++ b/test_programs/execution_success/conditional_1/Prover.toml @@ -0,0 +1,38 @@ +c=[2, 4, 3, 0, ] +a=0 +x = [104, 101, 108, 108, 111] + +result = [ + 0x2c, + 0xf2, + 0x4d, + 0xba, + 0x5f, + 0xb0, + 0xa3, + 0x0e, + 0x26, + 0xe8, + 0x3b, + 0x2a, + 0xc5, + 0xb9, + 0xe2, + 0x9e, + 0x1b, + 0x16, + 0x1e, + 0x5c, + 0x1f, + 0xa7, + 0x42, + 0x5e, + 0x73, + 0x04, + 0x33, + 0x62, + 0x93, + 0x8b, + 0x98, + 0x24, +] diff --git a/test_programs/execution_success/conditional_1/src/main.nr b/test_programs/execution_success/conditional_1/src/main.nr new file mode 100644 index 00000000000..eedb8a697d1 --- /dev/null +++ b/test_programs/execution_success/conditional_1/src/main.nr @@ -0,0 +1,91 @@ +fn sort(mut a: [u32; 4]) -> [u32; 4] { + for i in 1..4 { + for j in 0..i { + if a[i] < a[j] { + let c = a[j]; + a[j] = a[i]; + a[i] = c; + } + } + } + a +} + +fn must_be_zero(x: u8) { + assert(x == 0); +} + +fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { + //Test case for short-circuit + let mut data = [0 as u32; 32]; + let mut ba = a; + for i in 0..32 { + let i_u32 = i as u32; + if i_u32 == a { + for j in 0..4 { + data[i + j] = c[4 - 1 - j]; + for k in 0..4 { + ba = ba + data[k]; + } + if ba == 4864 { + c[3] = ba; + } + } + } + } + assert(data[31] == 0); + assert(ba != 13); + //Test case for conditional with arrays from function parameters + let b = sort([1, 2, 3, 4]); + assert(b[0] == 1); + + if a == 0 { + must_be_zero(0); + c[0] = 3; + } else { + must_be_zero(1); + c[0] = 1; + c[1] = c[2] / a + 11 % a; + let f1 = a as Field; + assert(10 / f1 != 0); + } + assert(c[0] == 3); + + let mut y = 0; + if a == 0 { + let digest = std::hash::sha256(x); + y = digest[0]; + } else { + y = 5; + } + assert(y == result[0]); + c = sort(c); + assert(c[0] == 0); + //test 1 + let mut x: u32 = 0; + if a == 0 { + c[0] = 12; + if a != 0 { + x = 6; + } else { + x = 2; + assert(x == 2); + } + } else { + x = 5; + assert(x == 5); + } + if c[0] == 0 { + x = 3; + } + assert(x == 2); + //test2: loops + let mut x: u32 = 0; + x = a - a; + for i in 0..4 { + if c[i] == 0 { + x = i as u32 + 2; + } + } + assert(x == 0); +} diff --git a/test_programs/execution_success/conditional_2/Nargo.toml b/test_programs/execution_success/conditional_2/Nargo.toml new file mode 100644 index 00000000000..153c5d38b99 --- /dev/null +++ b/test_programs/execution_success/conditional_2/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_2" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/conditional_2/Prover.toml b/test_programs/execution_success/conditional_2/Prover.toml new file mode 100644 index 00000000000..73fa4a5e31a --- /dev/null +++ b/test_programs/execution_success/conditional_2/Prover.toml @@ -0,0 +1,2 @@ +c=[2, 4, 3, 0, ] +a=0 diff --git a/test_programs/execution_success/conditional_2/src/main.nr b/test_programs/execution_success/conditional_2/src/main.nr new file mode 100644 index 00000000000..ea23ec3cf3b --- /dev/null +++ b/test_programs/execution_success/conditional_2/src/main.nr @@ -0,0 +1,49 @@ +fn must_be_zero(x: u8) { + assert(x == 0); +} + +fn test3(x: u8) { + if x == 0 { + must_be_zero(x); + } +} + +fn test4() -> [u32; 4] { + let b: [u32; 4] = [1, 2, 3, 4]; + b +} + +fn main(a: u32, mut c: [u32; 4]) { + test3(1); + + if a == 0 { + c = test4(); + } else { + assert(c[1] != 2); + } + if false { + c[1] = 5; + } + assert(c[1] == 2); + + test5(4); + // Test case for function synchronisation + let mut c_sync = 0; + if a == 42 { + c_sync = foo2(); + } else { + c_sync = foo2() + foo2(); + } + assert(c_sync == 6); +} + +fn test5(a: u32) { + if a > 1 { + let q = a / 2; + assert(q == 2); + } +} + +fn foo2() -> Field { + 3 +} diff --git a/test_programs/execution_success/conditional_regression_421/Nargo.toml b/test_programs/execution_success/conditional_regression_421/Nargo.toml new file mode 100644 index 00000000000..987b51ae126 --- /dev/null +++ b/test_programs/execution_success/conditional_regression_421/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_regression_421" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/conditional_regression_421/Prover.toml b/test_programs/execution_success/conditional_regression_421/Prover.toml new file mode 100644 index 00000000000..73fa4a5e31a --- /dev/null +++ b/test_programs/execution_success/conditional_regression_421/Prover.toml @@ -0,0 +1,2 @@ +c=[2, 4, 3, 0, ] +a=0 diff --git a/test_programs/execution_success/conditional_regression_421/src/main.nr b/test_programs/execution_success/conditional_regression_421/src/main.nr new file mode 100644 index 00000000000..5789afb76db --- /dev/null +++ b/test_programs/execution_success/conditional_regression_421/src/main.nr @@ -0,0 +1,10 @@ +fn main(a: u32, mut c: [u32; 4]) { + //Issue reported in #421 + if a == c[0] { + assert(c[0] == 0); + } else if a == c[1] { + assert(c[1] == 0); + } else if a == c[2] { + assert(c[2] == 0); + } +} diff --git a/test_programs/execution_success/conditional_regression_547/Nargo.toml b/test_programs/execution_success/conditional_regression_547/Nargo.toml new file mode 100644 index 00000000000..1a62c5af20c --- /dev/null +++ b/test_programs/execution_success/conditional_regression_547/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_regression_547" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/conditional_regression_547/Prover.toml b/test_programs/execution_success/conditional_regression_547/Prover.toml new file mode 100644 index 00000000000..3d2b4b14efe --- /dev/null +++ b/test_programs/execution_success/conditional_regression_547/Prover.toml @@ -0,0 +1 @@ +x = 1 \ No newline at end of file diff --git a/test_programs/execution_success/conditional_regression_547/src/main.nr b/test_programs/execution_success/conditional_regression_547/src/main.nr new file mode 100644 index 00000000000..7c09e6a2e20 --- /dev/null +++ b/test_programs/execution_success/conditional_regression_547/src/main.nr @@ -0,0 +1,20 @@ +fn main(x: Field) -> pub Field { + // Regression test for issue #547 + // Warning: it must be kept at the start of main + let arr: [u8; 2] = [1, 2]; + if arr[0] != arr[1] { + for i in 0..1 { + assert(i != 2); + } + } + // Regression for predicate simplification + x + safe_inverse(0) +} + +fn safe_inverse(n: Field) -> Field { + if n == 0 { + 0 + } else { + 1 / n + } +} diff --git a/test_programs/execution_success/conditional_regression_661/Nargo.toml b/test_programs/execution_success/conditional_regression_661/Nargo.toml new file mode 100644 index 00000000000..ed11341c5b0 --- /dev/null +++ b/test_programs/execution_success/conditional_regression_661/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_regression_661" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/conditional_regression_661/Prover.toml b/test_programs/execution_success/conditional_regression_661/Prover.toml new file mode 100644 index 00000000000..baad8be126a --- /dev/null +++ b/test_programs/execution_success/conditional_regression_661/Prover.toml @@ -0,0 +1,38 @@ +c=[2, 4, 3, 0, ] +a=0 +x = [104, 101, 108, 108, 111] + +result = [ + 0x2c, + 0xf2, + 0x4d, + 0xba, + 0x5f, + 0xb0, + 0xa3, + 0x0e, + 0x26, + 0xe8, + 0x3b, + 0x2a, + 0xc5, + 0xb9, + 0xe2, + 0x9e, + 0x1b, + 0x16, + 0x1e, + 0x5c, + 0x1f, + 0xa7, + 0x42, + 0x5e, + 0x73, + 0x04, + 0x33, + 0x62, + 0x93, + 0x8b, + 0x98, + 0x24, +] diff --git a/test_programs/execution_success/conditional_regression_661/src/main.nr b/test_programs/execution_success/conditional_regression_661/src/main.nr new file mode 100644 index 00000000000..1036acc6da4 --- /dev/null +++ b/test_programs/execution_success/conditional_regression_661/src/main.nr @@ -0,0 +1,28 @@ +fn main(a: u32, mut c: [u32; 4]) { + // Regression for issue #661: + let mut c_661: [u32; 1] = [0]; + if a > 5 { + c_661 = issue_661_foo(issue_661_bar(c), a); + } else { + c_661 = issue_661_foo(issue_661_bar(c), a + 2); + } + assert(c_661[0] < 20000); +} + +fn test5(a: u32) { + if a > 1 { + let q = a / 2; + assert(q == 2); + } +} + +fn issue_661_foo(array: [u32; 4], b: u32) -> [u32; 1] { + [array[0] + b] +} + +fn issue_661_bar(a: [u32; 4]) -> [u32; 4] { + let mut b: [u32; 4] = [0; 4]; + b[0] = a[0] + 1; + b +} + diff --git a/test_programs/execution_success/conditional_regression_short_circuit/Nargo.toml b/test_programs/execution_success/conditional_regression_short_circuit/Nargo.toml new file mode 100644 index 00000000000..92f5a869bc4 --- /dev/null +++ b/test_programs/execution_success/conditional_regression_short_circuit/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_regression_short_circuit" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/conditional_regression_short_circuit/Prover.toml b/test_programs/execution_success/conditional_regression_short_circuit/Prover.toml new file mode 100644 index 00000000000..baad8be126a --- /dev/null +++ b/test_programs/execution_success/conditional_regression_short_circuit/Prover.toml @@ -0,0 +1,38 @@ +c=[2, 4, 3, 0, ] +a=0 +x = [104, 101, 108, 108, 111] + +result = [ + 0x2c, + 0xf2, + 0x4d, + 0xba, + 0x5f, + 0xb0, + 0xa3, + 0x0e, + 0x26, + 0xe8, + 0x3b, + 0x2a, + 0xc5, + 0xb9, + 0xe2, + 0x9e, + 0x1b, + 0x16, + 0x1e, + 0x5c, + 0x1f, + 0xa7, + 0x42, + 0x5e, + 0x73, + 0x04, + 0x33, + 0x62, + 0x93, + 0x8b, + 0x98, + 0x24, +] diff --git a/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr b/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr new file mode 100644 index 00000000000..de5ad20a642 --- /dev/null +++ b/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr @@ -0,0 +1,36 @@ +fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { + //regression for short-circuit2 + if 35 == a { + assert(false); + } + bar(a as Field); + + if a == 3 { + c = test4(); + } + assert(c[1] != 2); + call_intrinsic(x, result); +} + +fn foo() { + let mut x = 1; + x /= 0; +} + +fn bar(x: Field) { + if x == 15 { + foo(); + } +} + +fn call_intrinsic(x: [u8; 5], result: [u8; 32]) { + let mut digest = std::hash::sha256(x); + digest[0] = 5 as u8; + digest = std::hash::sha256(x); + assert(digest == result); +} + +fn test4() -> [u32; 4] { + let b: [u32; 4] = [1, 2, 3, 4]; + b +} diff --git a/test_programs/execution_success/conditional_regression_underflow/Nargo.toml b/test_programs/execution_success/conditional_regression_underflow/Nargo.toml new file mode 100644 index 00000000000..75c4fb43b2f --- /dev/null +++ b/test_programs/execution_success/conditional_regression_underflow/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_regression_underflow" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/conditional_regression_underflow/Prover.toml b/test_programs/execution_success/conditional_regression_underflow/Prover.toml new file mode 100644 index 00000000000..ca65e8b9428 --- /dev/null +++ b/test_programs/execution_success/conditional_regression_underflow/Prover.toml @@ -0,0 +1 @@ +x = "4" \ No newline at end of file diff --git a/test_programs/execution_success/conditional_regression_underflow/src/main.nr b/test_programs/execution_success/conditional_regression_underflow/src/main.nr new file mode 100644 index 00000000000..aaf3754a20f --- /dev/null +++ b/test_programs/execution_success/conditional_regression_underflow/src/main.nr @@ -0,0 +1,15 @@ +// Regression test for https://github.com/noir-lang/noir/issues/3493 +fn main(x: u8) { + if x == 10 { + x + 255; + } + if x == 9 { + x << 7; + } + if x == 128 { + x * 3; + } + if x == 7 { + x - 8; + } +} diff --git a/test_programs/execution_success/custom_entry/Nargo.toml b/test_programs/execution_success/custom_entry/Nargo.toml new file mode 100644 index 00000000000..35cf2e080c1 --- /dev/null +++ b/test_programs/execution_success/custom_entry/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "custom_entry" +type = "bin" +entry = "src/foobarbaz.nr" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/custom_entry/Prover.toml b/test_programs/execution_success/custom_entry/Prover.toml new file mode 100644 index 00000000000..4dd6b405159 --- /dev/null +++ b/test_programs/execution_success/custom_entry/Prover.toml @@ -0,0 +1 @@ +x = "1" diff --git a/test_programs/execution_success/custom_entry/src/foobarbaz.nr b/test_programs/execution_success/custom_entry/src/foobarbaz.nr new file mode 100644 index 00000000000..00e94414c0b --- /dev/null +++ b/test_programs/execution_success/custom_entry/src/foobarbaz.nr @@ -0,0 +1,3 @@ +fn main(x: Field) { + assert(x == 1); +} diff --git a/test_programs/execution_success/databus/Nargo.toml b/test_programs/execution_success/databus/Nargo.toml new file mode 100644 index 00000000000..72360f7aefe --- /dev/null +++ b/test_programs/execution_success/databus/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "databus" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/databus/Prover.toml b/test_programs/execution_success/databus/Prover.toml new file mode 100644 index 00000000000..2d034508dd8 --- /dev/null +++ b/test_programs/execution_success/databus/Prover.toml @@ -0,0 +1,3 @@ +x = "3" +y = "4" +z = [1,2,3,4] diff --git a/test_programs/execution_success/databus/src/main.nr b/test_programs/execution_success/databus/src/main.nr new file mode 100644 index 00000000000..ecc7794cf9e --- /dev/null +++ b/test_programs/execution_success/databus/src/main.nr @@ -0,0 +1,12 @@ +fn main(mut x: u32, y: call_data(0) u32, z: call_data(0) [u32; 4]) -> return_data u32 { + let a = z[x]; + unsafe { + a + foo(y) + } +} + +// Use an unconstrained function to force the compiler to avoid inlining +unconstrained fn foo(x: u32) -> u32 { + x + 1 +} + diff --git a/test_programs/execution_success/databus_composite_calldata/Nargo.toml b/test_programs/execution_success/databus_composite_calldata/Nargo.toml new file mode 100644 index 00000000000..38c916e5d97 --- /dev/null +++ b/test_programs/execution_success/databus_composite_calldata/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "databus_composite_calldata" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/databus_composite_calldata/Prover.toml b/test_programs/execution_success/databus_composite_calldata/Prover.toml new file mode 100644 index 00000000000..ab154c13372 --- /dev/null +++ b/test_programs/execution_success/databus_composite_calldata/Prover.toml @@ -0,0 +1,11 @@ +zero = "0" +one = "1" +values = [[["12", "33"], ["37", "11"]],[["14", "37"], ["30", "10"]],[["10", "30"], ["30", "10"]]] + +[[foos]] +x = 1 +y = [1,2,3,4,5,6,7,8,9,0] + +[[foos]] +x = 2 +y = [1,2,3,5,6,8,7,8,9,0] \ No newline at end of file diff --git a/test_programs/execution_success/databus_composite_calldata/src/main.nr b/test_programs/execution_success/databus_composite_calldata/src/main.nr new file mode 100644 index 00000000000..fe6e2ed613a --- /dev/null +++ b/test_programs/execution_success/databus_composite_calldata/src/main.nr @@ -0,0 +1,16 @@ +struct Foo { + x: u32, + y: [u32; 10], +} + +fn main( + foos: call_data(0) [Foo; 2], + values: call_data(0) [[[u32; 2]; 2]; 3], + zero: u32, + one: u32, +) -> pub u32 { + assert_eq(foos[zero].x + 1, foos[one].x); + assert_eq(foos[zero].y[3] + 2, foos[one].y[4]); + assert_eq(values[zero][one][zero], values[one][zero][one]); + foos[zero].x + foos[one].y[0] +} diff --git a/test_programs/execution_success/databus_in_fn_with_empty_arr/Nargo.toml b/test_programs/execution_success/databus_in_fn_with_empty_arr/Nargo.toml new file mode 100644 index 00000000000..7c5caf7c771 --- /dev/null +++ b/test_programs/execution_success/databus_in_fn_with_empty_arr/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "databus_in_fn_with_empty_arr" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/databus_in_fn_with_empty_arr/Prover.toml b/test_programs/execution_success/databus_in_fn_with_empty_arr/Prover.toml new file mode 100644 index 00000000000..e84e0dd7eec --- /dev/null +++ b/test_programs/execution_success/databus_in_fn_with_empty_arr/Prover.toml @@ -0,0 +1,3 @@ +_empty = [] +value_1 = "1" +value_2 = "2" diff --git a/test_programs/execution_success/databus_in_fn_with_empty_arr/src/main.nr b/test_programs/execution_success/databus_in_fn_with_empty_arr/src/main.nr new file mode 100644 index 00000000000..85671978a33 --- /dev/null +++ b/test_programs/execution_success/databus_in_fn_with_empty_arr/src/main.nr @@ -0,0 +1,3 @@ +fn main(_empty: [u32; 0], value_1: u32, value_2: call_data(0) u32) { + assert_eq(value_1 + 1, value_2); +} diff --git a/test_programs/execution_success/databus_two_calldata/Nargo.toml b/test_programs/execution_success/databus_two_calldata/Nargo.toml new file mode 100644 index 00000000000..15d4b01ac44 --- /dev/null +++ b/test_programs/execution_success/databus_two_calldata/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "databus_two_calldata" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/databus_two_calldata/Prover.toml b/test_programs/execution_success/databus_two_calldata/Prover.toml new file mode 100644 index 00000000000..1229857d3f5 --- /dev/null +++ b/test_programs/execution_success/databus_two_calldata/Prover.toml @@ -0,0 +1,3 @@ +x = [0,1,2,3] +y = [0,2,4] +z = [1,3,5,7] diff --git a/test_programs/execution_success/databus_two_calldata/src/main.nr b/test_programs/execution_success/databus_two_calldata/src/main.nr new file mode 100644 index 00000000000..f19852ae8a0 --- /dev/null +++ b/test_programs/execution_success/databus_two_calldata/src/main.nr @@ -0,0 +1,15 @@ +// An simple program demonstrating two calldata array inputs and a single return data array. As an arbitrary example, +// the return data is computed as a linear combination of the calldata. +fn main( + mut x: [u32; 4], + y: call_data(0) [u32; 3], + z: call_data(1) [u32; 4], +) -> return_data [u32; 4] { + let mut result = [0; 4]; + for i in 0..3 { + let idx = x[i]; + result[idx] = y[idx] + z[idx]; + } + result[x[3]] = z[x[3]]; + result +} diff --git a/test_programs/execution_success/databus_two_calldata_simple/Nargo.toml b/test_programs/execution_success/databus_two_calldata_simple/Nargo.toml new file mode 100644 index 00000000000..5104029c08e --- /dev/null +++ b/test_programs/execution_success/databus_two_calldata_simple/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "databus_two_calldata_simple" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/databus_two_calldata_simple/Prover.toml b/test_programs/execution_success/databus_two_calldata_simple/Prover.toml new file mode 100644 index 00000000000..58257d1fe14 --- /dev/null +++ b/test_programs/execution_success/databus_two_calldata_simple/Prover.toml @@ -0,0 +1,3 @@ +idx = "1" +y = [7, 9] +z = [1,2,3,4] diff --git a/test_programs/execution_success/databus_two_calldata_simple/src/main.nr b/test_programs/execution_success/databus_two_calldata_simple/src/main.nr new file mode 100644 index 00000000000..2477f0006c8 --- /dev/null +++ b/test_programs/execution_success/databus_two_calldata_simple/src/main.nr @@ -0,0 +1,5 @@ +fn main(mut idx: u32, y: call_data(0) [u32; 2], z: call_data(1) [u32; 4]) -> return_data u32 { + let a = y[idx]; + let b = z[idx]; + a + b +} diff --git a/test_programs/execution_success/debug_logs/Nargo.toml b/test_programs/execution_success/debug_logs/Nargo.toml new file mode 100644 index 00000000000..9550d50cf15 --- /dev/null +++ b/test_programs/execution_success/debug_logs/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "debug_logs" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/debug_logs/Prover.toml b/test_programs/execution_success/debug_logs/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/debug_logs/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_success/debug_logs/src/main.nr b/test_programs/execution_success/debug_logs/src/main.nr new file mode 100644 index 00000000000..14344b1700b --- /dev/null +++ b/test_programs/execution_success/debug_logs/src/main.nr @@ -0,0 +1,140 @@ +fn main(x: Field, y: pub Field) { + let string = "i: {i}, j: {j}"; + println(string); + + // TODO: fmtstr cannot be printed + // let fmt_str: fmtstr<14, (Field, Field)> = f"i: {x}, j: {y}"; + // let fmt_fmt_str = f"fmtstr: {fmt_str}, i: {x}"; + // println(fmt_fmt_str); + // A `fmtstr` lets you easily perform string interpolation. + let fmt_str: fmtstr<14, (Field, Field)> = f"i: {x}, j: {y}"; + + let fmt_str = string_identity(fmt_str); + println(fmt_str); + + let fmt_str_no_type = f"i: {x}, j: {y}"; + println(fmt_str_no_type); + + let fmt_str_generic = string_with_generics(fmt_str_no_type); + println(fmt_str_generic); + + let s = myStruct { y: x, x: y }; + println(s); + + println(f"randomstring{x}{x}"); + + let fmt_str = string_with_partial_generics(f"i: {x}, s: {s}"); + println(fmt_str); + + println(x); + println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + println(f"s: {s}, foo: {foo}"); + + println(f"x: 0, y: 1"); + + let s_2 = myStruct { x: 20, y: 30 }; + println(f"s1: {s}, s2: {s_2}"); + + let bar = fooStruct { my_struct: s_2, foo: 20 }; + println(f"foo1: {foo}, foo2: {bar}"); + + let struct_string = if x != 5 { f"{foo}" } else { f"{bar}" }; + println(struct_string); + + let one_tuple = (1, 2, 3); + let another_tuple = (4, 5, 6); + println(f"one_tuple: {one_tuple}, another_tuple: {another_tuple}"); + println(one_tuple); + + let tuples_nested = (one_tuple, another_tuple); + println(f"tuples_nested: {tuples_nested}"); + println(tuples_nested); + + regression_2903(); + regression_2906(); + + let first_array = [1, 2, 3]; + let second_array = [4, 5, 6]; + let arrays_nested = [first_array, second_array]; + println(f"first_array: {first_array}, second_array: {second_array}"); + println(f"arrays_nested: {arrays_nested}"); + + let free_lambda = |x| x + 1; + let sentinel: u32 = 8888; + println(f"free_lambda: {free_lambda}, sentinel: {sentinel}"); + println(free_lambda); + + let one = 1; + 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)> { + string +} + +fn string_with_generics(string: fmtstr) -> fmtstr { + string +} + +fn string_with_partial_generics( + string: fmtstr, +) -> fmtstr { + string +} + +struct myStruct { + y: Field, + x: Field, +} + +struct fooStruct { + my_struct: myStruct, + foo: Field, +} + +fn regression_2903() { + let v: [str<1>; 1] = ["1"; 1]; + println(v); // will print [1] + let a = v[0]; + println(a); // will print `1` + let bytes = ["aaa", "bbb", "ccc"]; + println(bytes); +} + +fn regression_2906() { + let array_two_vals = [1, 2]; + println(f"array_two_vals: {array_two_vals}"); + + let label_two_vals = "12"; + println(f"label_two_vals: {label_two_vals}"); + + let array_five_vals = [1, 2, 3, 4, 5]; + println(f"array_five_vals: {array_five_vals}"); + + let label_five_vals = "12345"; + println(f"label_five_vals: {label_five_vals}"); + + 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/derive/Nargo.toml b/test_programs/execution_success/derive/Nargo.toml new file mode 100644 index 00000000000..f3846594305 --- /dev/null +++ b/test_programs/execution_success/derive/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "derive" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/derive/src/main.nr b/test_programs/execution_success/derive/src/main.nr new file mode 100644 index 00000000000..f7d4f6b607a --- /dev/null +++ b/test_programs/execution_success/derive/src/main.nr @@ -0,0 +1,89 @@ +use std::hash::Hash; + +#[derive_via(derive_do_nothing)] +trait DoNothing { + fn do_nothing(self); +} + +#[derive(DoNothing)] +struct MyStruct { + my_field: u32, +} + +comptime fn derive_do_nothing(s: StructDefinition) -> Quoted { + let typ = s.as_type(); + let generics = s.generics().map(|g| quote { $g }).join(quote {,}); + quote { + impl<$generics> DoNothing for $typ { + fn do_nothing(_self: Self) { + // Traits can't tell us what to do + println("something"); + } + } + } +} + +// Test stdlib derive fns & multiple traits +// - We can derive Ord and Hash even though std::cmp::Ordering and std::hash::Hasher aren't imported +// - We need to define MyOtherOtherStruct first since MyOtherStruct references it as a field and +// attributes are run in reading order. If it were defined afterward, the derived Eq impl for MyOtherStruct +// would error that MyOtherOtherStruct doesn't (yet) implement Eq. +#[derive(Eq, Default, Hash, Ord)] +struct MyOtherOtherStruct { + x: T, +} + +#[derive(Eq, Default, Hash, Ord)] +struct MyOtherStruct { + field1: A, + field2: B, + field3: MyOtherOtherStruct, +} + +#[derive(Eq, Default, Hash, Ord)] +struct EmptyStruct {} + +fn main() { + let s = MyStruct { my_field: 1 }; + s.do_nothing(); + + let o: MyOtherStruct = MyOtherStruct::default(); + assert_eq(o, o); + + let o: MyOtherStruct]> = MyOtherStruct::default(); + assert_eq(o, o); + + // Field & str<2> above don't implement Ord + let o1 = MyOtherStruct { + field1: 12 as u32, + field2: 24 as i8, + field3: MyOtherOtherStruct { x: 54 as i8 }, + }; + let o2 = MyOtherStruct { + field1: 12 as u32, + field2: 24 as i8, + field3: MyOtherOtherStruct { x: 55 as i8 }, + }; + assert(o1 < o2); + + let mut hasher = TestHasher { result: 0 }; + o1.hash(&mut hasher); + assert_eq(hasher.finish(), 12 + 24 + 54); + + let empty = EmptyStruct {}; + assert_eq(empty, empty); +} + +struct TestHasher { + result: Field, +} + +impl std::hash::Hasher for TestHasher { + fn finish(self) -> Field { + self.result + } + + fn write(&mut self, input: Field) { + self.result += input; + } +} diff --git a/test_programs/execution_success/diamond_deps_0/Nargo.toml b/test_programs/execution_success/diamond_deps_0/Nargo.toml new file mode 100644 index 00000000000..8b75d71ae12 --- /dev/null +++ b/test_programs/execution_success/diamond_deps_0/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "diamond_deps_0" +type = "bin" +authors = [""] + +[dependencies] +dep1 = { path = "../../test_libraries/diamond_deps_1" } +dep2 = { path = "../../test_libraries/diamond_deps_2" } diff --git a/test_programs/execution_success/diamond_deps_0/Prover.toml b/test_programs/execution_success/diamond_deps_0/Prover.toml new file mode 100644 index 00000000000..2bad103177c --- /dev/null +++ b/test_programs/execution_success/diamond_deps_0/Prover.toml @@ -0,0 +1,3 @@ +x = 1 +y = 1 +return = 7 diff --git a/test_programs/execution_success/diamond_deps_0/src/main.nr b/test_programs/execution_success/diamond_deps_0/src/main.nr new file mode 100644 index 00000000000..690d6fc9fc8 --- /dev/null +++ b/test_programs/execution_success/diamond_deps_0/src/main.nr @@ -0,0 +1,7 @@ +use dep1::call_dep1_then_dep2; +use dep2::call_dep2; +use dep2::RESOLVE_THIS; + +fn main(x: Field, y: pub Field) -> pub Field { + call_dep1_then_dep2(x, y) + call_dep2(x, y) + RESOLVE_THIS +} diff --git a/test_programs/execution_success/double_verify_honk_proof/Nargo.toml b/test_programs/execution_success/double_verify_honk_proof/Nargo.toml new file mode 100644 index 00000000000..5f819990c72 --- /dev/null +++ b/test_programs/execution_success/double_verify_honk_proof/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "double_verify_honk_proof" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/double_verify_honk_proof/Prover.toml b/test_programs/execution_success/double_verify_honk_proof/Prover.toml new file mode 100644 index 00000000000..f8e7ba41a18 --- /dev/null +++ b/test_programs/execution_success/double_verify_honk_proof/Prover.toml @@ -0,0 +1,5 @@ +key_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" +proof = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x1a4249b90be4602c8ff40c7c276160ee41b2a0f8a238ce7706e9face2db03d48", "0x162204b9d54d3ffd285c393a5a1ff76ee681474fd780a21a3cf7fac5c24fc2b9", "0x30279eb953d8ee79b2155c69c04e6443c5de6bf7e02886256dd7b3cd3c9502a4", "0x0d32c1bd21baf43e72d5d82d461ef54833807ff81a877adc822f27a6db88d754", "0x0fe15e055c0803d5ebe6dd77689b70cfd82138f008810ce24535c992daaff27d", "0x1fba82c012671212ce2fc13fd09bf8fba4f7d5875ab8d37495d1ccfcff287331", "0x090738a5842fa4d2699b3726aa0dd97cb59569b4be2c6825335ec4969f859dc2", "0x0c6cb72dabbc28abcf4a50c203534e066c29f48c24ca64d672092f263df3f9d7", "0x0f27fbea0d9145f815c288b50fe7e8c10b8185d325b5264624fd57102855d05d", "0x2a815cd3fd1c43c72ee0130465250ff771d1e7be2347e4ada331b83265a03450", "0x148b4ecf2ad7ed17409417086867ee27bc1b0906dbc9cbb3714c285071e2db70", "0x08e700a42b1d6d36ee65f8ebedf47d3a44463ff9fa579dce13b7492e20142c3a", "0x2e23c69521d572ff2152c50f8c9a9191535f4cf37f95f1e0428692e78842b642", "0x14519e0354365923fb41400c19866135b45e975d56a0980260bc99f0390b1d5f", "0x04caded1f05738f736cb5bcf08d785e395e58eb7738523a20638aa16bc51593e", "0x28787eaccd38383215ea21ec02895c32d979f68ca155f534a2e2d377bff6698b", "0x20a1b81fa96c58cf11c5762c5ceb731efdcb081fca2d34d5c463d2cf40e6da18", "0x11789a06fe3bf53833741d180f068d29534d5bb58a5c64b8119542e62b189fb4", "0x23d00fcd032ace719ffcbc513bfa177a55b04377d76455c2788d999d05d011e2", "0x01f0e81b57b4a73cc118e51ede18f8724debf25c2d109db6ef45280f99f1a3fa", "0x156d1c9b61749810de728f259c2c1c1fd4dbff97101426e26087ca461c93307c", "0x1c5d619ac3a478cfd06d5eebfd879960bb321236be173813f5e78d1366d32c69", "0x250cfae4e1dfc551406f1f3d10b649a637dcb7bcb0f6f697994cf96afd35d0c1", "0x242b999f58cf5f53c874d1092bd38725aa9ea076f5bc8f176efa9ea23393874b", "0x2e15748255c4a5e0e9fe38047341b692a967257de27a85a3a38681bc9f1602ea", "0x01ef83886ea7017253699cb6371988eb8e21b4f7023d7479ece4907fe6d4a6fd", "0x08db2dbc271e375b9312f695c59c48f313235b3432cad50921c8d9ad6dd7ad7a", "0x199309f2c2cd45c15a4abb0e6554a1615ff5a6e9488a8d900bbf835fc8f664ef", "0x074be7a3d88e31ab1b59c9208c012bcfb1f85f351c709e68134996891db52b57", "0x301b1011354d2ebf46134fc4d6d734bb6ed8542d719f38f5e09a376a580cad7f", "0x12968f3eccaa27e44f14d5aaac6ecb70c00d040e07536292e685d7cab03fc563", "0x2110a023c8c22fd2ed70270a2d0a265b92a32ce2217ffe1be9a5d7d5c25f512f", "0x1e8cf4c60c53900f0430d5b44de5804fe8b38299bc803beeb4216e1a289cf624", "0x12301cb908ccb28a2616e29b831ec7105b5d3ebf45ff5fe91d50a9dd53a50b52", "0x0f1029ed107d84ff2d6d4a416cbd01da3f3d7bf5b2209ce93ba424f4b85616fc", "0x1b431d016611b8abd684afd9e92331c3325967b1116bfa91d4f44e2f8e2c9fc2", "0x281e335a0fd117064c8ace3f01e02b134a19e9b9220571ebfaaaa0e3a12d34db", "0x22559c106f77e2ae95677d5e38e288343e3b7168371aec7d3aaab9ef8150af70", "0x13f113b1d9b590149cf08c3f6e90589cda5c7b98528866b891256cb9d5d814e7", "0x10252ef388e4c80246962e98b9e976fab2cd25e1e6f1e3fd2a7d4786c5218a97", "0x16b890723dfdebd9912a9207255f95cb800222165b6fae97ec46e461f23e83f3", "0x25caf77c7d2e8e069341ec90f3c8f6d64319cfd2d77cab0625cf0377285ba11c", "0x016c84288b0bc3c50eebbe250cdd5a4ee50b2c65a24ac64d0c930cbdecb95141", "0x20a537c045b069d47dc6315f45b391f60681222381e5059ec7c8b17bf677d911", "0x2594c0edfcd4064d215a3d797bc8e3b2f401c61f3961ae96ccbec8f8fd29e81f", "0x1c831d7047483ca00ed59bdb84c47ffb8bbebbae92aa164c7b35fcffbb8a35d3", "0x2ea7f60de52b8cd6b0bd06f861fc1f2c5ed1d1fbfa53caccdb836400a03df434", "0x275c6c8bd115f7d2ce196439e2330fad305c6745bab0bf1ce3f2fa32dadc3c43", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2b3f4e210619347288731e7f0eea1ae60dd8696fe87319044864d099a03a9536", "0x0fecd3d2aebedeb8be2b0b7e3a74de9ec8bd2cb72851541463729e0715aef48b", "0x10bee385ad0c2cd3ff88ef4d630840749e4367f9add4a300fc4f545a7778e92c", "0x1fe792730eeafbd22c4eb80e86e2b40108b1e55b2a08db786289eea5745b9e3b", "0x04d411679da432816b213cd5580dda1fd6c2f258684c036be19b5b26baca583c", "0x159f17b655d2b8a803e0cfb564918628be52d3baa950ca1b127854491624f8f4", "0x225340463867d9252a1269013536e2e1dd219aa18eadef13c324b63d44679334", "0x1885e231554e02abb40ed54b72ebf09b883d0298a6bc06fc645a30365f370ef2", "0x233344517f25170972b8ba35d01f2df2e073d322993abce7df26796126e93498", "0x08990e8faa13b18b4433ec417c5cc596885e11ffd372d5f612c08cc79a5d5c80", "0x1e960a0c892b755c28e21dcbed816c1b182d7da43bae07f8ee622bd4485f79e7", "0x27b58e2ee290a179d349ace82752528b2ff946d60c092b99ef42f53c25d0c99f", "0x2a5cf8a3193107d982edd253002c7a52ab876b445dde8307ab78fbdca022d93c", "0x2b1ab4d5277f8c82750c1c7bd043889b71465ec64a9afc1bfa37d06b1ebd0725", "0x2a0dbf5c4373a58a83d5f2a031ea0615bf12800e33b70c3191a7cbb15966ced8", "0x1f272bb4a19d14a0abdfebc9fc83125e10623b9aef730f8d25f2bf5bead38ea9", "0x2c2339cf0ae7aff56091a568c1e2c3f01f52d8ed13400737fd31eaabcaffb9bd", "0x21f5fefe6b5fa0b5da71089befb74a1a39e52b4f830cb330c3c284e154614dfd", "0x1e6f6ba4b2444586b380dc4e2b3fad111ff1f4754420a846f53ea0789ebfb0ad", "0x1193d170b0b2dd0c4a04331a4b4aa3f12920f182ec3ab547837e30f1116ca584", "0x00000000000000000000000000000025704a15c9e2ce8a69558e7bbcdcbc7784", "0x2e5d36112770fb6c985681cafe40a8c99ad13f702309e7969801dd0ed080e727", "0x0eefc2585f591bb457183134e19ad643966272234d645514bf7868d6dd8ae2cb", "0x300803e4e2339ad39b9c31f228949bbeaf9c74b7101e7be1930b088126247eaa", "0x2bb562a50ed944b438b83b01f200101a34faef7f296a75c84c731755ebddbc1a", "0x1288e0b9c742af39cbcac21357c1b29511b0bbdd3d0e3cf5e14b2eef68a28ab3", "0x20f089131cc96d86ff1cfb67fa3f51670f4bad30158751b2587354bbec76cdf9", "0x1a26c6d3e633f9bf8434cf755b5f1217dad0d455071a97a7bcf85b824f5cf07a", "0x0d7e9b8a51fccf910ec25bdbd13e70b34bd6ea6f4d629fa744f9cdf5f2beb1cf", "0x0b40f28ce428e64df9cf5a024133fc420f39decf5f6af020cc3211ab298d4631", "0x0ca4f189dde7a55fe829f46681232904f6670249a22e0deb47222bd309523a8a", "0x2c544f2e31143783977645edb2a6bdb39b875053963bfa1a5b3ae9de204a7ebe", "0x00aae4454eb48fb18ff60db6b9d015abea2e770a2f7d86d121522b834c791ba5", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x2d9e5bff47207d82533e2445959941181cc890c5779bc7f24d6e8a7b9e425b5c", "0x0aea3c0c317c441a5775a9849108d7a6889b39128235f717b09b184aa08e4eb7", "0x1ca5bc6fb37c55a562f4991901c39902f42d14db71284116df74cb4e7d55e493", "0x220fed26d64cd69f40e6d145a423e4a3c8cd0dce747e7d51647441270ad4d774", "0x15be574c9358889257aa2a30ff7b5fcc31a57da7032296e2c1201c49a44bbdb6", "0x2de539925525bedd3b7f43a9c6bf0f713151a17f79ac7ff4a9cd27b15ffe892a", "0x083086693dbf465211741e2cbff70ff38eb08383faf22d397eb2742c8ad7396a", "0x1fdfa258a890598816e807c50058d7a1462edd5ff196a2eae0f862e454b49aa1", "0x10c434c6daaa8226fa8e3e302123dfdc4455cf68063df518949df5a65a945213", "0x0000000000000000000000000000006472a7874de2c454a4591ed7784df1c104", "0x000000000000000000000000000000000008c46ac53d2c4ad0c26a5d6c790082", "0x0000000000000000000000000000005e422f9cfb8725800de60dfe0a8d4104c0", "0x000000000000000000000000000000000000f10fd4e4de81a0c00073ec91c274", "0x000000000000000000000000000000b20813090eca76bc6aa4a699b1ec8d5d6d", "0x0000000000000000000000000000000000292cc9f8a744eb00e0903c29ce87a7", "0x000000000000000000000000000000350a368b415fbb99fa90a26a42b1a3affd", "0x0000000000000000000000000000000000280eb9275cb05a3435f464d1dc369d", "0x000000000000000000000000000000280df6505e20c7725fe6d29439f96ee05d", "0x000000000000000000000000000000000017ef5033a08535451e2747827aa94b", "0x0000000000000000000000000000002f9ba89ae91b4e4a4ff8ccbd0526faad2f", "0x00000000000000000000000000000000001c2013561dafcc02cb03220bdf23c4", "0x000000000000000000000000000000aac102c400f9e5da0321ded4510994434b", "0x00000000000000000000000000000000001ec8ab9cc834b492fde124962f04a1", "0x0000000000000000000000000000000673dbd698da8b8cce450d2a083aba9987", "0x00000000000000000000000000000000000a49e55bb040249cb41c63cea901cd", "0x000000000000000000000000000000133d92af8d76ee0c74a12081ee7b2ef8c4", "0x0000000000000000000000000000000000240f552d1c6cbb007650e4b142e0a5", "0x000000000000000000000000000000e29c6e7d982ec08d51c79d6261c28d742d", "0x000000000000000000000000000000000021baeec04d9be419c923626034e7b3", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x1e940a528b42d8230e7d4dff76262a80986c0d00b2c02a9bc0559e36212d1547", "0x1ceccf21ac39f70d76ad6f7fe0dcb33b6af04555a0b1959e4714d65925e4e253", "0x096139d757046cdbdb7ee89a95f112f70882a43a46c2f739d9be115dda013420", "0x2f9c8ac67c7825b08eff0e7f7656a671f4c64e5601f2efab35b1b795801eec04", "0x2077e648e1704851cdffd7e6e56311634a7b741bab77ca34d9dff12a6a2bfe99", "0x115d48c4a97aeb3c447a060f9e0d675b0dc7f4a05a3f5776e2f279f3a165d7dc", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000fd38c45c3ec5b841482a80e3a56ce82555", "0x00000000000000000000000000000000000ad70b03f092f60af3e0ce1bb29d2c", "0x0000000000000000000000000000007a184d5342c90c634c0b1a050f0b97c9fb", "0x0000000000000000000000000000000000271f42abcb3bc1f0332e4b3ca85e1d", "0x0000000000000000000000000000008256322bbe2c1b8cd9d84e5ff6123477f2", "0x000000000000000000000000000000000025cab962761681dd9547f4c78814df", "0x0000000000000000000000000000008c4234510e5825c02b9ac427bcbf8e279a", "0x000000000000000000000000000000000013a14e0d7fc073c44643af38cc5396"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005", "0x0000000000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000007", "0x0000000000000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000009", "0x000000000000000000000000000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000000000000000000000000000b", "0x000000000000000000000000000000000000000000000000000000000000000c", "0x000000000000000000000000000000000000000000000000000000000000000d", "0x000000000000000000000000000000000000000000000000000000000000000e", "0x000000000000000000000000000000000000000000000000000000000000000f", "0x0000000000000000000000000000000000000000000000000000000000000010", "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3"] +proof_b = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x1a4249b90be4602c8ff40c7c276160ee41b2a0f8a238ce7706e9face2db03d48", "0x162204b9d54d3ffd285c393a5a1ff76ee681474fd780a21a3cf7fac5c24fc2b9", "0x30279eb953d8ee79b2155c69c04e6443c5de6bf7e02886256dd7b3cd3c9502a4", "0x0d32c1bd21baf43e72d5d82d461ef54833807ff81a877adc822f27a6db88d754", "0x0fe15e055c0803d5ebe6dd77689b70cfd82138f008810ce24535c992daaff27d", "0x1fba82c012671212ce2fc13fd09bf8fba4f7d5875ab8d37495d1ccfcff287331", "0x090738a5842fa4d2699b3726aa0dd97cb59569b4be2c6825335ec4969f859dc2", "0x0c6cb72dabbc28abcf4a50c203534e066c29f48c24ca64d672092f263df3f9d7", "0x0f27fbea0d9145f815c288b50fe7e8c10b8185d325b5264624fd57102855d05d", "0x2a815cd3fd1c43c72ee0130465250ff771d1e7be2347e4ada331b83265a03450", "0x148b4ecf2ad7ed17409417086867ee27bc1b0906dbc9cbb3714c285071e2db70", "0x08e700a42b1d6d36ee65f8ebedf47d3a44463ff9fa579dce13b7492e20142c3a", "0x2e23c69521d572ff2152c50f8c9a9191535f4cf37f95f1e0428692e78842b642", "0x14519e0354365923fb41400c19866135b45e975d56a0980260bc99f0390b1d5f", "0x04caded1f05738f736cb5bcf08d785e395e58eb7738523a20638aa16bc51593e", "0x28787eaccd38383215ea21ec02895c32d979f68ca155f534a2e2d377bff6698b", "0x20a1b81fa96c58cf11c5762c5ceb731efdcb081fca2d34d5c463d2cf40e6da18", "0x11789a06fe3bf53833741d180f068d29534d5bb58a5c64b8119542e62b189fb4", "0x23d00fcd032ace719ffcbc513bfa177a55b04377d76455c2788d999d05d011e2", "0x01f0e81b57b4a73cc118e51ede18f8724debf25c2d109db6ef45280f99f1a3fa", "0x156d1c9b61749810de728f259c2c1c1fd4dbff97101426e26087ca461c93307c", "0x1c5d619ac3a478cfd06d5eebfd879960bb321236be173813f5e78d1366d32c69", "0x250cfae4e1dfc551406f1f3d10b649a637dcb7bcb0f6f697994cf96afd35d0c1", "0x242b999f58cf5f53c874d1092bd38725aa9ea076f5bc8f176efa9ea23393874b", "0x2e15748255c4a5e0e9fe38047341b692a967257de27a85a3a38681bc9f1602ea", "0x01ef83886ea7017253699cb6371988eb8e21b4f7023d7479ece4907fe6d4a6fd", "0x08db2dbc271e375b9312f695c59c48f313235b3432cad50921c8d9ad6dd7ad7a", "0x199309f2c2cd45c15a4abb0e6554a1615ff5a6e9488a8d900bbf835fc8f664ef", "0x074be7a3d88e31ab1b59c9208c012bcfb1f85f351c709e68134996891db52b57", "0x301b1011354d2ebf46134fc4d6d734bb6ed8542d719f38f5e09a376a580cad7f", "0x12968f3eccaa27e44f14d5aaac6ecb70c00d040e07536292e685d7cab03fc563", "0x2110a023c8c22fd2ed70270a2d0a265b92a32ce2217ffe1be9a5d7d5c25f512f", "0x1e8cf4c60c53900f0430d5b44de5804fe8b38299bc803beeb4216e1a289cf624", "0x12301cb908ccb28a2616e29b831ec7105b5d3ebf45ff5fe91d50a9dd53a50b52", "0x0f1029ed107d84ff2d6d4a416cbd01da3f3d7bf5b2209ce93ba424f4b85616fc", "0x1b431d016611b8abd684afd9e92331c3325967b1116bfa91d4f44e2f8e2c9fc2", "0x281e335a0fd117064c8ace3f01e02b134a19e9b9220571ebfaaaa0e3a12d34db", "0x22559c106f77e2ae95677d5e38e288343e3b7168371aec7d3aaab9ef8150af70", "0x13f113b1d9b590149cf08c3f6e90589cda5c7b98528866b891256cb9d5d814e7", "0x10252ef388e4c80246962e98b9e976fab2cd25e1e6f1e3fd2a7d4786c5218a97", "0x16b890723dfdebd9912a9207255f95cb800222165b6fae97ec46e461f23e83f3", "0x25caf77c7d2e8e069341ec90f3c8f6d64319cfd2d77cab0625cf0377285ba11c", "0x016c84288b0bc3c50eebbe250cdd5a4ee50b2c65a24ac64d0c930cbdecb95141", "0x20a537c045b069d47dc6315f45b391f60681222381e5059ec7c8b17bf677d911", "0x2594c0edfcd4064d215a3d797bc8e3b2f401c61f3961ae96ccbec8f8fd29e81f", "0x1c831d7047483ca00ed59bdb84c47ffb8bbebbae92aa164c7b35fcffbb8a35d3", "0x2ea7f60de52b8cd6b0bd06f861fc1f2c5ed1d1fbfa53caccdb836400a03df434", "0x275c6c8bd115f7d2ce196439e2330fad305c6745bab0bf1ce3f2fa32dadc3c43", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2b3f4e210619347288731e7f0eea1ae60dd8696fe87319044864d099a03a9536", "0x0fecd3d2aebedeb8be2b0b7e3a74de9ec8bd2cb72851541463729e0715aef48b", "0x10bee385ad0c2cd3ff88ef4d630840749e4367f9add4a300fc4f545a7778e92c", "0x1fe792730eeafbd22c4eb80e86e2b40108b1e55b2a08db786289eea5745b9e3b", "0x04d411679da432816b213cd5580dda1fd6c2f258684c036be19b5b26baca583c", "0x159f17b655d2b8a803e0cfb564918628be52d3baa950ca1b127854491624f8f4", "0x225340463867d9252a1269013536e2e1dd219aa18eadef13c324b63d44679334", "0x1885e231554e02abb40ed54b72ebf09b883d0298a6bc06fc645a30365f370ef2", "0x233344517f25170972b8ba35d01f2df2e073d322993abce7df26796126e93498", "0x08990e8faa13b18b4433ec417c5cc596885e11ffd372d5f612c08cc79a5d5c80", "0x1e960a0c892b755c28e21dcbed816c1b182d7da43bae07f8ee622bd4485f79e7", "0x27b58e2ee290a179d349ace82752528b2ff946d60c092b99ef42f53c25d0c99f", "0x2a5cf8a3193107d982edd253002c7a52ab876b445dde8307ab78fbdca022d93c", "0x2b1ab4d5277f8c82750c1c7bd043889b71465ec64a9afc1bfa37d06b1ebd0725", "0x2a0dbf5c4373a58a83d5f2a031ea0615bf12800e33b70c3191a7cbb15966ced8", "0x1f272bb4a19d14a0abdfebc9fc83125e10623b9aef730f8d25f2bf5bead38ea9", "0x2c2339cf0ae7aff56091a568c1e2c3f01f52d8ed13400737fd31eaabcaffb9bd", "0x21f5fefe6b5fa0b5da71089befb74a1a39e52b4f830cb330c3c284e154614dfd", "0x1e6f6ba4b2444586b380dc4e2b3fad111ff1f4754420a846f53ea0789ebfb0ad", "0x1193d170b0b2dd0c4a04331a4b4aa3f12920f182ec3ab547837e30f1116ca584", "0x00000000000000000000000000000025704a15c9e2ce8a69558e7bbcdcbc7784", "0x2e5d36112770fb6c985681cafe40a8c99ad13f702309e7969801dd0ed080e727", "0x0eefc2585f591bb457183134e19ad643966272234d645514bf7868d6dd8ae2cb", "0x300803e4e2339ad39b9c31f228949bbeaf9c74b7101e7be1930b088126247eaa", "0x2bb562a50ed944b438b83b01f200101a34faef7f296a75c84c731755ebddbc1a", "0x1288e0b9c742af39cbcac21357c1b29511b0bbdd3d0e3cf5e14b2eef68a28ab3", "0x20f089131cc96d86ff1cfb67fa3f51670f4bad30158751b2587354bbec76cdf9", "0x1a26c6d3e633f9bf8434cf755b5f1217dad0d455071a97a7bcf85b824f5cf07a", "0x0d7e9b8a51fccf910ec25bdbd13e70b34bd6ea6f4d629fa744f9cdf5f2beb1cf", "0x0b40f28ce428e64df9cf5a024133fc420f39decf5f6af020cc3211ab298d4631", "0x0ca4f189dde7a55fe829f46681232904f6670249a22e0deb47222bd309523a8a", "0x2c544f2e31143783977645edb2a6bdb39b875053963bfa1a5b3ae9de204a7ebe", "0x00aae4454eb48fb18ff60db6b9d015abea2e770a2f7d86d121522b834c791ba5", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x2d9e5bff47207d82533e2445959941181cc890c5779bc7f24d6e8a7b9e425b5c", "0x0aea3c0c317c441a5775a9849108d7a6889b39128235f717b09b184aa08e4eb7", "0x1ca5bc6fb37c55a562f4991901c39902f42d14db71284116df74cb4e7d55e493", "0x220fed26d64cd69f40e6d145a423e4a3c8cd0dce747e7d51647441270ad4d774", "0x15be574c9358889257aa2a30ff7b5fcc31a57da7032296e2c1201c49a44bbdb6", "0x2de539925525bedd3b7f43a9c6bf0f713151a17f79ac7ff4a9cd27b15ffe892a", "0x083086693dbf465211741e2cbff70ff38eb08383faf22d397eb2742c8ad7396a", "0x1fdfa258a890598816e807c50058d7a1462edd5ff196a2eae0f862e454b49aa1", "0x10c434c6daaa8226fa8e3e302123dfdc4455cf68063df518949df5a65a945213", "0x0000000000000000000000000000006472a7874de2c454a4591ed7784df1c104", "0x000000000000000000000000000000000008c46ac53d2c4ad0c26a5d6c790082", "0x0000000000000000000000000000005e422f9cfb8725800de60dfe0a8d4104c0", "0x000000000000000000000000000000000000f10fd4e4de81a0c00073ec91c274", "0x000000000000000000000000000000b20813090eca76bc6aa4a699b1ec8d5d6d", "0x0000000000000000000000000000000000292cc9f8a744eb00e0903c29ce87a7", "0x000000000000000000000000000000350a368b415fbb99fa90a26a42b1a3affd", "0x0000000000000000000000000000000000280eb9275cb05a3435f464d1dc369d", "0x000000000000000000000000000000280df6505e20c7725fe6d29439f96ee05d", "0x000000000000000000000000000000000017ef5033a08535451e2747827aa94b", "0x0000000000000000000000000000002f9ba89ae91b4e4a4ff8ccbd0526faad2f", "0x00000000000000000000000000000000001c2013561dafcc02cb03220bdf23c4", "0x000000000000000000000000000000aac102c400f9e5da0321ded4510994434b", "0x00000000000000000000000000000000001ec8ab9cc834b492fde124962f04a1", "0x0000000000000000000000000000000673dbd698da8b8cce450d2a083aba9987", "0x00000000000000000000000000000000000a49e55bb040249cb41c63cea901cd", "0x000000000000000000000000000000133d92af8d76ee0c74a12081ee7b2ef8c4", "0x0000000000000000000000000000000000240f552d1c6cbb007650e4b142e0a5", "0x000000000000000000000000000000e29c6e7d982ec08d51c79d6261c28d742d", "0x000000000000000000000000000000000021baeec04d9be419c923626034e7b3", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x1e940a528b42d8230e7d4dff76262a80986c0d00b2c02a9bc0559e36212d1547", "0x1ceccf21ac39f70d76ad6f7fe0dcb33b6af04555a0b1959e4714d65925e4e253", "0x096139d757046cdbdb7ee89a95f112f70882a43a46c2f739d9be115dda013420", "0x2f9c8ac67c7825b08eff0e7f7656a671f4c64e5601f2efab35b1b795801eec04", "0x2077e648e1704851cdffd7e6e56311634a7b741bab77ca34d9dff12a6a2bfe99", "0x115d48c4a97aeb3c447a060f9e0d675b0dc7f4a05a3f5776e2f279f3a165d7dc", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000fd38c45c3ec5b841482a80e3a56ce82555", "0x00000000000000000000000000000000000ad70b03f092f60af3e0ce1bb29d2c", "0x0000000000000000000000000000007a184d5342c90c634c0b1a050f0b97c9fb", "0x0000000000000000000000000000000000271f42abcb3bc1f0332e4b3ca85e1d", "0x0000000000000000000000000000008256322bbe2c1b8cd9d84e5ff6123477f2", "0x000000000000000000000000000000000025cab962761681dd9547f4c78814df", "0x0000000000000000000000000000008c4234510e5825c02b9ac427bcbf8e279a", "0x000000000000000000000000000000000013a14e0d7fc073c44643af38cc5396"] \ No newline at end of file diff --git a/test_programs/execution_success/double_verify_honk_proof/src/main.nr b/test_programs/execution_success/double_verify_honk_proof/src/main.nr new file mode 100644 index 00000000000..82090bb8602 --- /dev/null +++ b/test_programs/execution_success/double_verify_honk_proof/src/main.nr @@ -0,0 +1,28 @@ +// This circuit aggregates two Honk proof from `assert_statement`. +global SIZE_OF_PROOF_IF_LOGN_IS_28: u32 = 463; +global HONK_IDENTIFIER: u32 = 1; +fn main( + verification_key: [Field; 128], + // 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; SIZE_OF_PROOF_IF_LOGN_IS_28], + public_inputs: pub [Field; 1], + key_hash: Field, + // The second proof, currently set to be identical + proof_b: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], +) { + std::verify_proof_with_type( + verification_key, + proof, + public_inputs, + key_hash, + HONK_IDENTIFIER, + ); + std::verify_proof_with_type( + verification_key, + proof_b, + public_inputs, + key_hash, + HONK_IDENTIFIER, + ); +} diff --git a/test_programs/execution_success/double_verify_nested_proof/Nargo.toml b/test_programs/execution_success/double_verify_nested_proof/Nargo.toml new file mode 100644 index 00000000000..3ead649c879 --- /dev/null +++ b/test_programs/execution_success/double_verify_nested_proof/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "double_verify_nested_proof" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/double_verify_nested_proof/Prover.toml b/test_programs/execution_success/double_verify_nested_proof/Prover.toml new file mode 100644 index 00000000000..2a2b4b33586 --- /dev/null +++ b/test_programs/execution_success/double_verify_nested_proof/Prover.toml @@ -0,0 +1,5 @@ +key_hash = "0x13fd5b632ce9e9d12c9ac56c150ed09413df3edf40d1b7ab8ced9f262ec61b29" +proof_b = ["0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000004bdfb9b586a637ceebd99ff26dcd3af427","0x0000000000000000000000000000000000265c2a5caf8e033e32d192807f5353","0x000000000000000000000000000000c0ab1db6ea40ac087cdc82c4a61ab00c86","0x0000000000000000000000000000000000010800ea8010f4bd3dd432d1cc11ed","0x000000000000000000000000000000eb3db3c41e3e636d686fd2903b1b913a01","0x000000000000000000000000000000000009bbab6b90377114c9e33d2a302226","0x000000000000000000000000000000758726e60ef4b211cf1c965fe08293365b","0x0000000000000000000000000000000000290ec193bc7f4f9006b9cea136bff5","0x0000000000000000000000000000005a2a389cd1702b3aa37f30ed974147d343","0x00000000000000000000000000000000001d83087d6efe0db3f482730b8d5e32","0x000000000000000000000000000000ad015051ed84c11d061e63eddbc3c0417a","0x0000000000000000000000000000000000155011c8b0167ff694740c48d67683","0x00000000000000000000000000000010c638a3b13dba3e77be3f10a3d096927c","0x00000000000000000000000000000000002372b9853214a1f76e5636dc26f146","0x00000000000000000000000000000005d9ca201c07bd4216689677feb9227715","0x000000000000000000000000000000000001dcf09921797dffb8eb21abef187b","0x00000000000000000000000000000070af16c9644b777dcf84d69e820e1ed895","0x00000000000000000000000000000000002d5e8f7eb7a4e20964dd94dc141534","0x0000000000000000000000000000003636871dbe453b366c3351be6e84144683","0x0000000000000000000000000000000000206464e290e4f4764365038ac77edf","0x000000000000000000000000000000175c20da35cc833dd542af57de9b62a2da","0x00000000000000000000000000000000001d2e31de3715e05ff6278f88e5a0db","0x000000000000000000000000000000328610e4eabb48be78d3c75f7c159205c5","0x000000000000000000000000000000000026720634b8076fee0a17b358b04653","0x0000000000000000000000000000000e5f48906892ffbff91e8b58ceabba0949","0x000000000000000000000000000000000013c349df687926ccb712622fc72a36","0x000000000000000000000000000000a4b8c9046c7e7e4cc19bbf9a367668eac7","0x00000000000000000000000000000000002a81128e53672c33bb0dae0ff18f41","0x000000000000000000000000000000edb79df57c4a2303ed1e5c2d7ed1e1bdaf","0x000000000000000000000000000000000018d3cea4ce204eafd70c0ded024650","0x000000000000000000000000000000e5f82856854fe0a2d587f6a9ae8555f321","0x0000000000000000000000000000000000235480ec2adc05f04261054345e568","0x00000000000000000000000000000083607465f60b70b092f606853f4d9e96eb","0x000000000000000000000000000000000006569e3a3174bcb71efe46f7fb7e0f","0x000000000000000000000000000000cb4d5fc546f20f63e3b7cf60341956f36f","0x00000000000000000000000000000000000e14b1932630bf606a637eabb7c80f","0x000000000000000000000000000000786f31c2e082aa7e398e6323bb48a27472","0x00000000000000000000000000000000002dd72746f5e5a4a438def122ae6bba","0x000000000000000000000000000000d007be60a28b744e49279fab277c8bd623","0x00000000000000000000000000000000000e52e2b940b9cd8d001209cc40f7c8","0x000000000000000000000000000000dd4357e24a1bda0b5a6c5eee657cfe9091","0x0000000000000000000000000000000000047bb24b20feb0b66089a96671c901","0x0000000000000000000000000000003fe7f42f34e3360ef0fa8bd9c17e6190a3","0x0000000000000000000000000000000000161d17a3848118e91b435b553d34e9","0x216fa2905e105e0c767687f9b5e81c2e4ce03abe2993ac8dcd9e8d89e088966f","0x1288ba942d41c7f4b048e125454253bc7d7ffc0875365c0b8f75a2bb3ea90b42","0x1ad706f84cffcc62fa030f1bc57cb478a687aa74c1019beeda9bab4e40d35373","0x03050c8016b8041a557a46840ab4166a9c2531eb7c3985a447996a334e0caf5f","0x2b3c485da75bdaef8cec120bd08bc21e3ff717740114d13d3811006215a1fb24","0x008fc8c76c4d8cbba8653bf0919c047d379941be60c7afc7250bc6bfc5f29ad5","0x1993ae2a0da54e5e643533fdefbf54a0df21115b2ee79a63a7f477c2c9c4a5d5","0x22520fa7fde2d72b9776c07c9b897ef7ce48f8a7937ec0cacb01d3e23f72b78a","0x259b7b9c1dbfe88d613102f0e8548f0c770a1c83876b26a5cb4b6790740cb487","0x043006102e519b8011d089f51811337fbdedc856a73842f7c8197be176b08d38","0x2222bd509df909ce38b67b3172b24c8ce1e0e1dd0d811f4fae6957e3418415ac","0x1b1204474652fa85979f0274145680718bed80466f4c91ad58f37df1b4fe2395","0x08d57251b42c0697535617ae239d7f3ef9d1558c1bb71fa01c68e7b5fd266139","0x04ca7f21f1d0ba50ecf00c615d18bf8f7291bb04f513cbef78fb6d03ed9b0cb2","0x070ae1119c80846863a4cd971e535ff87fe34473eb5730b14e5b30212b7b78a1","0x1128027ded5032cc265c96ff81d76e2ce06420702fd4e5bc4e24fda695961651","0x1ef7a9e5885b934eee2b44335157309de2f60519e50a8471e5e24495dff2a9fe","0x2d0dad89e5633da796c0c897804575879bc5dc7ad3805b44260943101ac9609e","0x287edcbd60e9d636ba1cd1c9ff3ec2b71b694112c65876525f5e2f8209cd747f","0x24b1157a1cb5bdbd2829de066b8c5573584f9b8638bf9bad476a1fe1172da4b9","0x1f9825731638cd1c43f7cf035b808a1704f122453318cb88fe3b1164f034e170","0x07003a6552f3a6ab1ad3e0717be0af049767b554ff88986c4e48224632523405","0x288002c2ff29874077b2c216a35cb61ecc97d12750a3a86574d50acd42607095","0x0a12fc37918ce7dcbd0d354a05bdbb409a8e4530d86f3d8ce07231240590f65c","0x2ec631b05fc693b07286eecf6b6ac1aef0d073cdced8e050244ec7cf4e8f6e42","0x107bc98da225efe7749d51b9966c3edd6c245f2e5cf183a924ba982817e4525a","0x2ca603f77ea0ca42b6f38cd43bc3cc09442906373a2f197fdc976533066ac343","0x138ace5653809375aa9d95240fa9b6508860a471aed70bcc8b7dd52ae34809f3","0x21e1eb924951881c3d0ce5657d2e26a3e5150ce8f49c9e4d0476c5fdf1e43a54","0x2e2daec93f5e94f6784ce569883cf285da12244b38fb001b94bfb99bb4de060c","0x186a8d30c973bef6286115865a690a2528adbeea8376e5221fffeb6a135d9904","0x1e0d9d90628be31ebc16ef1d85d5f9e6fb8cb57e6a74e576f958cf21db45042e","0x124ceb5e1d9da6d0fe163e961643bb0423c926ef4e0c583eaba9e32d99ec6c7c","0x2db34cc38a50bfea50750830710c13b4d80f4ec0e8df8f186047ee36f338eeeb","0x0b174aa403b42235d5bdde8e9f5bb6c52ae62fec2884334cbe3e53418bd2463d","0x1571ebd9c3854c2f63418f206c6937495450ab9238a238b9c63fbf5867378c5b","0x24f92d1ab27e5810e5b7f4b31254526822f866602922258135c5eb5a2b21ca04","0x20cc7f5ba8df67d9c95642e2662654eb2305c6a280ce1747aec88a581ee50647","0x24112b99f63bbda7487709396dff22aae89ae809263021b65503ff7f809c7e38","0x06805c80f64efd1fa7f08382c9981aad9cecad78808da670477566674141bc48","0x146d4801d6f5898051ee0d7c95375a65ea0e6deeac6ffee1d9b9cf64da72dc3e","0x000000000000000000000000000000425b99a5c96b22ba0286d9ebeecf8e4559","0x0000000000000000000000000000000000110be4b8fe46a96303c205d3a1d61d","0x000000000000000000000000000000d9ff7ae757f2f0c91d1f1e71fac1b27b74","0x000000000000000000000000000000000009b0c285f6c221f6eba93b1e330ac4","0x0000000000000000000000000000004055cd5738a25ab1860a1e35555962dc19","0x00000000000000000000000000000000001a8726ccf54e17cf1b005e3e04879a","0x0000000000000000000000000000007be4dc343e9c2e0d4a9156f1ef9769f65a","0x00000000000000000000000000000000002b0e96f68f6509615ca0544dfa3107"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x2260e724844bca5251829353968e4915305258418357473a5c1d597f613f6cbd","0x0000000000000000000000000000000000000000000000000000000000080000","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000080000","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000004","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000006","0x0000000000000000000000000000000000000000000000000000000000000007","0x0000000000000000000000000000000000000000000000000000000000000008","0x0000000000000000000000000000000000000000000000000000000000000009","0x000000000000000000000000000000000000000000000000000000000000000a","0x000000000000000000000000000000000000000000000000000000000000000b","0x000000000000000000000000000000000000000000000000000000000000000c","0x000000000000000000000000000000000000000000000000000000000000000d","0x000000000000000000000000000000000000000000000000000000000000000e","0x000000000000000000000000000000000000000000000000000000000000000f","0x0000000000000000000000000000000000000000000000000000000000000010","0x000000000000000000000000000000ba765ed919550454064328e0fd7c51ff4a","0x00000000000000000000000000000000000418b2f4104c289eb20cb95344c850","0x0000000000000000000000000000006defa500aab13c8cf3c00117db573bef2c","0x000000000000000000000000000000000026dea3ea8fb7e77b5bfa8443397dc7","0x0000000000000000000000000000009a5c33c4054817f3402e68aeca4728a405","0x00000000000000000000000000000000002abf5ea67ec384cb2e5998c7a48b3a","0x000000000000000000000000000000ee78817f7d959ea45abb27404e3371c708","0x0000000000000000000000000000000000260a979e8190a83b0bce1351b92d3c","0x000000000000000000000000000000ec447bd83a83883ce4c11573ce24845c74","0x000000000000000000000000000000000005b23c2076f50d10baa061a67b9200","0x00000000000000000000000000000058ffc16cfb64ec06a56a2b1a9047fb8f0c","0x000000000000000000000000000000000011d2f5833d720e1d0a02749471e7ad","0x000000000000000000000000000000416dd6c8c0d1cbb185b3c3197eac767d0b","0x000000000000000000000000000000000023b9c5a4e525926d64247ec92e0baf","0x000000000000000000000000000000a55f5f52ebc8936a58e413a1068d94d376","0x00000000000000000000000000000000000be3f377ccc88a6cb5df6f230da95e","0x00000000000000000000000000000070a162a08d4d4800f450af94888f8f3480","0x0000000000000000000000000000000000085883b02590372a7b36a1c57db4c3","0x00000000000000000000000000000045b0b661ea73930ee3327ccff8a0ca9ce1","0x00000000000000000000000000000000002854cab8629792eb07e9ef81bc46ee","0x00000000000000000000000000000067f365021e0e42117c43a39419d1d9cc73","0x000000000000000000000000000000000022c370b38f0a97eb3d718146f2284b","0x00000000000000000000000000000016de6670aba605233072b8eecfa9069b06","0x000000000000000000000000000000000002c29c49d66457bcbd4fa5bf6096fd","0x000000000000000000000000000000e32e8ce4f18ba30ce53245044d0c60508a","0x00000000000000000000000000000000001170220489121b8eedd58a4b5599df","0x000000000000000000000000000000139ed828b410380d053ec0f056656f5703","0x0000000000000000000000000000000000072aebdce25ba333c86769adec1362","0x000000000000000000000000000000aa352ee565f91fc2b73323fc824bc14636","0x00000000000000000000000000000000001f3e272a192808ec9283ee3bb4df4b","0x00000000000000000000000000000005c72c8c88be0259ae226ccb0488452b4b","0x00000000000000000000000000000000001c68407d694502b929b77cbbab8374","0x0000000000000000000000000000003716bda8267f29931ed0aa811e4607f1c6","0x000000000000000000000000000000000007d888936af2141bb2f6823a587e81","0x0000000000000000000000000000004cf1a4f39c5363f70ecc9e433d751ea529","0x00000000000000000000000000000000002e8a81232ec84e48032178f1ee6edb","0x000000000000000000000000000000388e8265061fa0c92c96fc85d99bac7891","0x00000000000000000000000000000000002e3c516222565332e6e7362400bc5f","0x0000000000000000000000000000003a68d13661a0906e5828fe8271a336bf64","0x00000000000000000000000000000000001412d3e67497c98e5ec2aaee8779f5","0x000000000000000000000000000000b5d123498733b5279d8bcbade0d8345ef7","0x00000000000000000000000000000000000fa572890537089a5fb36953e7a1ca","0x0000000000000000000000000000004d8ff057fc9936a693035266c80c6ea57d","0x00000000000000000000000000000000001907a614968d777fcc506f639799f6","0x00000000000000000000000000000010769533212d3cafbf6ac378c8055c33a2","0x00000000000000000000000000000000000eac32851272327acdc0890792dfb7","0x000000000000000000000000000000e3e32f343643d319a977beb0c2b0ab9b31","0x00000000000000000000000000000000000c10c4c9dce6ff648ef70f54d45ba6","0x00000000000000000000000000000025721304165b9b313b94cf2c77b61dc1ef","0x000000000000000000000000000000000024b8083b0f323c2703a7255caa7078","0x0000000000000000000000000000002b860372c65049c88f6532cbd360917b11","0x000000000000000000000000000000000011ee2ac2bc36cdfdc107eca47369f3","0x0000000000000000000000000000001c1b0233882acb5a78a977642e4dce91d5","0x000000000000000000000000000000000020922a70853993b3516eeb01d7c8a4","0x0000000000000000000000000000001f90b5fade69a55a2da8d2db3c62b62d7c","0x0000000000000000000000000000000000173312bb89c6722b548ff87a7487a2","0x0000000000000000000000000000009d618ffd933cf58a8a0953dc76f97cf108","0x00000000000000000000000000000000000ddc3b6d8e59cf0996ca71ad4132ca","0x000000000000000000000000000000ec4c6a253f431d3f3fc06aa0e5b0448b8c","0x0000000000000000000000000000000000153193287060386695f4f2d0d3525d","0x0000000000000000000000000000004bd25585edb9319128045c005d48491b1e","0x00000000000000000000000000000000001170f0ece62f8c572bca96b141d27f","0x0000000000000000000000000000003dd2e37b8edb1f56b785809d7710bf1c88","0x0000000000000000000000000000000000246cd041690f653f88ed0c56ad282a","0x00000000000000000000000000000034bc8a00ce9d452888e5fc2b5a7e14fed7","0x000000000000000000000000000000000026153c937447356a0c6d6be09d85eb","0x000000000000000000000000000000555388ad9364679246b07992f84b4e91b2","0x0000000000000000000000000000000000189da022421fbd8dfd7973084d978e","0x000000000000000000000000000000e8c0f9753e2a5a35acec051fafe2cecce5","0x0000000000000000000000000000000000285311c5e9a4cbb56a3f04f29d5443","0x00000000000000000000000000000092d2d0ac76a1be7f1fad96cbd997175312","0x00000000000000000000000000000000002436400260c9d3180beedd0bf49fec","0x000000000000000000000000000000887d86d95387bbb29616cc5c41ee4a2669","0x0000000000000000000000000000000000063bf32f8addf7a3e1cf6cd223cb71","0x000000000000000000000000000000d841dc7d9da6cc699e8377b2a04723fea0","0x00000000000000000000000000000000002ce091428268c212a2bcfea0edb338","0x00000000000000000000000000000012fe4771092fa47e4d6050701527133f09","0x00000000000000000000000000000000002f36672865c5ae4976486fdaf2d81d","0x0000000000000000000000000000008e6bced56a3d94dfe9d476da3a424b8eff","0x00000000000000000000000000000000002d6303cf28aa721f4e5348a0d83642","0x0000000000000000000000000000008c5807dace05b2079d200f7f71caffdaf7","0x000000000000000000000000000000000008f7beb50cb16f3b6210aff1bdb05d","0x0000000000000000000000000000004f9ee08a49536eb54a238b982c4dfd5446","0x000000000000000000000000000000000014f55e7065eabacf1a7d6cbf1f6765","0x00000000000000000000000000000021150153ec654b02a66d9bea056185877e","0x00000000000000000000000000000000000e7bf50a142b21057bcfd340a5e77c","0x00000000000000000000000000000038110629263a662f10464b375f988cccda","0x00000000000000000000000000000000001964a0ab814f71282cd159df492710","0x000000000000000000000000000000b9310dd49ea52ba735b9654ebced7bc67b","0x000000000000000000000000000000000019ad72f92554ce44921ca3f420f995","0x000000000000000000000000000000d67d7e81fa6e1cdfae6d84510a8cb7e257","0x00000000000000000000000000000000000a6ec9d85c10a85e8f31eaedb4e459"] +proof = ["0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x00000000000000000000000000000063cb03b1d83ae3942e11ca8ec63055898b","0x00000000000000000000000000000000001edaf70d547a857fbed6a9ff8a38c9","0x000000000000000000000000000000097fb881332193ff4489e213f600e6a007","0x00000000000000000000000000000000001f2903742639c3595d22b96d4d9c21","0x000000000000000000000000000000bca7215bb1bcdde52ed9cf845b7e54072d","0x0000000000000000000000000000000000188bd12b19073eb01e8be5bda41b3e","0x0000000000000000000000000000007d1a114656606c391bfb286ea4e14062a5","0x000000000000000000000000000000000026d8a3b8821da41b6b1d6b85872260","0x000000000000000000000000000000c49078b857741b82cba39d8a394c1876c1","0x00000000000000000000000000000000002f9b9f76f80a4ff456e60c024f8d03","0x0000000000000000000000000000004bab3e60680935219213ea32be70ec5100","0x00000000000000000000000000000000002c45bda56f0115cfde2678889694ab","0x0000000000000000000000000000006434e56313172088d5a6b10fdd1b94b4ca","0x000000000000000000000000000000000007ad41e7980534fc2f89e8ad7366ad","0x00000000000000000000000000000023d769c68ef65f0b4f06a01e655fb265e7","0x0000000000000000000000000000000000008d3b5d5b201ed6773c369fe20d10","0x0000000000000000000000000000005eacdd2121ba4b1cf0df09632df6991fcf","0x0000000000000000000000000000000000005e98e857c8c1eb16cef913e44f90","0x0000000000000000000000000000003449da35dc7c0b67b0c3e99ced603ea381","0x000000000000000000000000000000000022347c8daec6739b183413a787fd13","0x000000000000000000000000000000df23d8f1ac4ddfced428737db15e63f603","0x000000000000000000000000000000000015e03670ba72d84269d764d8f8e725","0x000000000000000000000000000000457a7f854dbab545c8c94ccdb8e4b9ad45","0x00000000000000000000000000000000000a268fc41b7031912cec59dc0a7078","0x00000000000000000000000000000022fcb55824b67af33225f8f2e614fbbdb4","0x0000000000000000000000000000000000235f698e6aee7bf8ca94f4a44db006","0x000000000000000000000000000000a327da390bd3e01e4a7b639605fdfd9c42","0x0000000000000000000000000000000000210196c4fb53d660a3824867b2b1c5","0x000000000000000000000000000000728fb44750fa2b956221bd441fa61e32d6","0x0000000000000000000000000000000000073db9e2cafdf0fe22b5090855533e","0x0000000000000000000000000000004fe310e93730876891eebab46db9496dbc","0x000000000000000000000000000000000007d3574fe79c87011abdbd51a46670","0x000000000000000000000000000000adc522f42e085c51403fc50c83f35904b9","0x00000000000000000000000000000000000d2d9ef8fc0031b4568842a99b34eb","0x00000000000000000000000000000098586d928c8abc7cc56d571c8eded52168","0x000000000000000000000000000000000024279c001a40e94d3d149ec01a468a","0x00000000000000000000000000000066122aaf47d9d5060a2ce1d17cc5201be0","0x00000000000000000000000000000000001c21031d83d52e27867a611229d2ca","0x000000000000000000000000000000838dfc066499f7715682f755b42f3a4869","0x00000000000000000000000000000000001f816d2c5b2e903496f1443cb91de3","0x0000000000000000000000000000007ef917b6df805f430f8a0833942a7c3094","0x00000000000000000000000000000000000a9cefe716f31dbe37485179d60f0e","0x00000000000000000000000000000028adb1040bd0c07448de51d5cac9fd0495","0x00000000000000000000000000000000000c66b25a22c8b3ba82ec09ab4bdef3","0x2cc791d253f03f47cc88f7f0aeae481762f4aa6426712772544aaeca72466cb7","0x14197950f448f679eeff75c4e83dac9f0ebd5aa194709ea3875fb4e4b15bc2f2","0x1a92022c2ed8f8a41e3f392e22f1875f6916543bbb22c3aaf50d703de649c381","0x2ee77a26e78d5e1093dabd3612beee4b515a4f159992138e13ecd3f0afcfba18","0x2c280cba627b147142a2d333ee856000298708f9b5df0cc8d23c26d0936d6869","0x1b2569bb6f6b60b6f743ff892a39a490770d4ad40a961a06149d4968b0487a40","0x2f80351e43621d69b7e620338b2822e15dec9e6a2de16e8d04bb559153cd53a3","0x15a78b8ae9b3be431b609250b69c7cb746c6a689b2122150f258c6f7d67409fc","0x1334c47f273be542576813933e89a9130a342846272b39a2eab3ab7fc022d5fe","0x1031bdcafc5c0dad81c8b6c4931c9b442cd0c8a0bb9a729cc2f6bf0a18dc1b82","0x177f92f0cef76c5c45f55d16fa2be426354cdd4af6ac9aaad479c9b47f88656d","0x0064c0e0ec8984d612189e5287d59eedc1a6de52fc78bf72028f744350c27a0e","0x2c06222cf0d415c976e6904f1706b77cf438636ada3222e1c31c4957d6877dac","0x173da534b7001f44f19bb3e3f8601ac94fbf90b2e39b7d4079d8fac2d65102ea","0x012909bcdbd1167010cf0084028e851f3448f58946f4951b1b8d544d86b138c8","0x2975c3987f110c06bd8ced1d8bb0d398ac72c6f196ea639bdde58fa4b899d4a0","0x05c196fb2f6ccfd92a38ae526af85bccc3695ea0e2561e7a211c60360187602d","0x18a288590dd0cbfe5b7652458c9caddc9eac2f08e5822b64141ed1b4e805bda3","0x0cd08c41605b22a7ae31c3961486f645a32bff0ccaef63b6d661ef356db78560","0x05d5e48184693259f722f84ea48f9b84667d1e9db19e1381b2279fe24b01484b","0x2187a6f6a2398e5f0137880a983ff6b682b5a7c2b62e4bdfff6ff6becd0d53ab","0x1d4764ca9346e8ac48675320521e0daba651f480efe932302e8a9673580fc0d8","0x00cfcb920adeb0293acf26e63aeac4489622e4c806b93f1c72f8491cba3d0196","0x1bcd6a556800b8385ba1250afd69999fe2bb5518a6ba2cc461a4afba21ffbedb","0x11a15b3c8ef0e4ac0ff151fba72b922f6c005519151a4f88557352265944aeea","0x063d550a154f2ce80b08fb169d137fa96dcea6a6c489e98e1390aa9a5db18928","0x25da993132041b9f667de044194f5c6b0cdae961cdea5f6dbbda8595f213ac08","0x22fcecc2e3794814bbb84700031cd75ec9817201c8c88df2e86407a14412f902","0x01583d25d2f91d646da02a520d3dbf758b0a0590a533bd1417a717fd0cd18915","0x18ebacffdc81e15547232dfc1a0e31ec2848a1e5b9c8509a92432c2549d93091","0x20a3d15aa70d04a841802fe1d990f56c6b9e6eadc17da2c0dfd2a817e6cf0430","0x0b497cc2e54412ce07c52effdce6c01de2c1a0e1d095a2a37f5351232400c0a1","0x14419bb69d02675b8d58e60ce88a2f4b6a43674461e4015e2e302285a42c5784","0x0c84db03ff77d0729bb68eab2d6d697b7caebd4ea3db781499492a6f0ef67765","0x1a676b1c6b0ab1c85b31af681e05751296c3d0a1a883668f5fe971827ce86fc9","0x08da949bf7603bfe20f3c152abe727051c6306cff322197e8fa56b390f565b5b","0x1fd77e041239f94e907dc3ae3069a70cbff726b9d8b3a368a4910c8a070a9c9a","0x03755d83a4f0fdfbb4fd1b2b465842e1bb707a419c2952a2ca9faba50d4be379","0x0ee90c8166adcb238d85c72a85db2248353610c55390a2ed54e59dd1c35c12d2","0x170bcd78efaa1b19bcfd065c2ec60b48aa1e62465df73e62f3bd291115315144","0x015d60e5cc5c7d67853993261bd9e3c6e56f95dee8724ce79c7601ee10c1a731","0x000000000000000000000000000000f0a8b99d65fc1555bafb688233a6489aea","0x0000000000000000000000000000000000043849f038ec96c8c1c6e242351361","0x0000000000000000000000000000001ad41d3dfebb280623d5b325f0a7aa38f7","0x00000000000000000000000000000000002e5f2119536daa9e6d1f9b82b797dd","0x000000000000000000000000000000e5570c2b6e74d0994e2fc8be1a9dab4160","0x00000000000000000000000000000000002ed426a78ed52d4c13f2c651a6d4ec","0x000000000000000000000000000000aba14637487e4d3ca30dc397416696c85c","0x000000000000000000000000000000000005ae1eb3eee0cdf5e5c7bb0ac9be07"] 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 new file mode 100644 index 00000000000..8dde07cae19 --- /dev/null +++ b/test_programs/execution_success/double_verify_nested_proof/src/main.nr @@ -0,0 +1,24 @@ +// 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 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. + // I believe we want to eventually make it public too though. + key_hash: Field, + proof_b: [Field; 109], +) { + std::verify_proof(verification_key, proof, public_inputs, key_hash); + + std::verify_proof(verification_key, proof_b, public_inputs, key_hash); +} diff --git a/test_programs/execution_success/double_verify_proof/Nargo.toml b/test_programs/execution_success/double_verify_proof/Nargo.toml new file mode 100644 index 00000000000..c5954f54bdb --- /dev/null +++ b/test_programs/execution_success/double_verify_proof/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "double_verify_proof" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/double_verify_proof/Prover.toml b/test_programs/execution_success/double_verify_proof/Prover.toml new file mode 100644 index 00000000000..dff48212e50 --- /dev/null +++ b/test_programs/execution_success/double_verify_proof/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/src/main.nr b/test_programs/execution_success/double_verify_proof/src/main.nr new file mode 100644 index 00000000000..8f9fbf7bec5 --- /dev/null +++ b/test_programs/execution_success/double_verify_proof/src/main.nr @@ -0,0 +1,17 @@ +// This circuit aggregates two proofs from `assert_statement`. +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, proof, public_inputs, key_hash); + + std::verify_proof(verification_key, proof_b, public_inputs, key_hash); +} diff --git a/test_programs/execution_success/ecdsa_secp256k1/Nargo.toml b/test_programs/execution_success/ecdsa_secp256k1/Nargo.toml new file mode 100644 index 00000000000..58fdf96f0e3 --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256k1/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ecdsa_secp256k1" +description = "ECDSA secp256k1 verification" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/ecdsa_secp256k1/Prover.toml b/test_programs/execution_success/ecdsa_secp256k1/Prover.toml new file mode 100644 index 00000000000..412c7b36e4c --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256k1/Prover.toml @@ -0,0 +1,209 @@ + +hashed_message = [ + 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, +] +message = [ + 0x49, + 0x6e, + 0x73, + 0x74, + 0x72, + 0x75, + 0x63, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x20, + 0x75, + 0x6e, + 0x63, + 0x6c, + 0x65, + 0x61, + 0x72, + 0x2c, + 0x20, + 0x61, + 0x73, + 0x6b, + 0x20, + 0x61, + 0x67, + 0x61, + 0x69, + 0x6e, + 0x20, + 0x6c, + 0x61, + 0x74, + 0x65, + 0x72, + 0x2e, +] +pub_key_x = [ + 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, +] +pub_key_y = [ + 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, +] +signature = [ + 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, +] diff --git a/test_programs/execution_success/ecdsa_secp256k1/src/main.nr b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr new file mode 100644 index 00000000000..00d420089fc --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr @@ -0,0 +1,15 @@ +fn main( + message: [u8; 38], + hashed_message: [u8; 32], + pub_key_x: [u8; 32], + pub_key_y: [u8; 32], + signature: [u8; 64], +) { + // Hash the message, since secp256k1 expects a hashed_message + let expected = std::hash::sha256(message); + assert(hashed_message == expected); + + let valid_signature = + std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} diff --git a/test_programs/execution_success/ecdsa_secp256r1/Nargo.toml b/test_programs/execution_success/ecdsa_secp256r1/Nargo.toml new file mode 100644 index 00000000000..87e8d529566 --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ecdsa_secp256r1" +description = "ECDSA secp256r1 verification" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/ecdsa_secp256r1/Prover.toml b/test_programs/execution_success/ecdsa_secp256r1/Prover.toml new file mode 100644 index 00000000000..a45f799877b --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1/Prover.toml @@ -0,0 +1,20 @@ +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 +] + + diff --git a/test_programs/execution_success/ecdsa_secp256r1/src/main.nr b/test_programs/execution_success/ecdsa_secp256r1/src/main.nr new file mode 100644 index 00000000000..d65e4a371b9 --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1/src/main.nr @@ -0,0 +1,5 @@ +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/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..ab9b70e52df --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr @@ -0,0 +1,32 @@ +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/embedded_curve_ops/Nargo.toml b/test_programs/execution_success/embedded_curve_ops/Nargo.toml new file mode 100644 index 00000000000..1c389149aaf --- /dev/null +++ b/test_programs/execution_success/embedded_curve_ops/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "embedded_curve_ops" +type = "bin" +authors = [""] + +[dependencies] 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..85cf60dc796 --- /dev/null +++ b/test_programs/execution_success/embedded_curve_ops/src/main.nr @@ -0,0 +1,41 @@ +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.x == pub_x); + assert(res.y == 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.x); + + // Tests for #6549 + let const_scalar1 = std::embedded_curve_ops::EmbeddedCurveScalar { lo: 23, hi: 0 }; + let const_scalar2 = std::embedded_curve_ops::EmbeddedCurveScalar { lo: 0, hi: 23 }; + let const_scalar3 = std::embedded_curve_ops::EmbeddedCurveScalar { lo: 13, hi: 4 }; + let partial_mul = std::embedded_curve_ops::multi_scalar_mul( + [g1, double, pub_point, g1, g1], + [scalar, const_scalar1, scalar, const_scalar2, const_scalar3], + ); + assert(partial_mul.x == 0x2024c4eebfbc8a20018f8c95c7aab77c6f34f10cf785a6f04e97452d8708fda7); + // Check simplification by zero + let zero_point = std::embedded_curve_ops::EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }; + let const_zero = std::embedded_curve_ops::EmbeddedCurveScalar { lo: 0, hi: 0 }; + let partial_mul = std::embedded_curve_ops::multi_scalar_mul( + [zero_point, double, g1], + [scalar, const_zero, scalar], + ); + assert(partial_mul == g1); +} diff --git a/test_programs/execution_success/encrypted_log_regression/Nargo.toml b/test_programs/execution_success/encrypted_log_regression/Nargo.toml new file mode 100644 index 00000000000..5c2623b3a1c --- /dev/null +++ b/test_programs/execution_success/encrypted_log_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "encrypted_log_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/execution_success/encrypted_log_regression/Prover.toml b/test_programs/execution_success/encrypted_log_regression/Prover.toml new file mode 100644 index 00000000000..7ca8c21a692 --- /dev/null +++ b/test_programs/execution_success/encrypted_log_regression/Prover.toml @@ -0,0 +1,9 @@ +# Using the smaller sizes defined in `main.nr`. +# The reason this program is in the `execution_success` directory is because +# `rebuild.sh` only goes over these programs, but all we really care about is +# any potential future bytecode size regression. +eph_pk_bytes = [1, 2, 3] +incoming_header_ciphertext = [1, 2] +incoming_body_ciphertext = [9, 8, 7, 6, 5, 4, 3, 2, 1] +flag = true +return = [1, 2, 3, 1, 2, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1] diff --git a/test_programs/execution_success/encrypted_log_regression/src/main.nr b/test_programs/execution_success/encrypted_log_regression/src/main.nr new file mode 100644 index 00000000000..c65f580b0c8 --- /dev/null +++ b/test_programs/execution_success/encrypted_log_regression/src/main.nr @@ -0,0 +1,94 @@ +// The code below is inspired by [compute_encrypted_log](https://github.com/AztecProtocol/aztec-packages/blob/b42756bc10175fea9eb60544759e9dbe41ae5e76/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr#L111) +// which resulted in a bytecode size blowup when compiled to ACIR, see https://github.com/noir-lang/noir/issues/6929 +// The issue was around `encrypted_bytes[offset + i]` generating large amounts of gates, as per the `flamegraph.sh` tool in aztec-packages. +// The details around encryption and addresses have been stripped away, focusing on just copying bytes of equivalent size arrays. + +// Original values which resulted in huge bytecode even on this example (500K long SSA) +// global PRIVATE_LOG_SIZE_IN_FIELDS: u32 = 18; +// global ENCRYPTED_PAYLOAD_SIZE_IN_BYTES: u32 = (PRIVATE_LOG_SIZE_IN_FIELDS - 1) * 31; +// global EPH_PK_SIZE: u32 = 32; +// global HEADER_SIZE: u32 = 48; +// global OVERHEAD_PADDING: u32 = 15; + +// Using the same formulas with smaller numbers; the effect is the same, but the SSA is more manageable. +global PRIVATE_LOG_SIZE_IN_FIELDS: u32 = 4; +global ENCRYPTED_PAYLOAD_SIZE_IN_BYTES: u32 = (PRIVATE_LOG_SIZE_IN_FIELDS - 1) * 5; +global EPH_PK_SIZE: u32 = 3; +global HEADER_SIZE: u32 = 2; +global OVERHEAD_PADDING: u32 = 1; + +// Unused because encryption didn't play a role: +// global OVERHEAD_SIZE: u32 = EPH_PK_SIZE + HEADER_SIZE + OVERHEAD_PADDING; +// global PLAINTEXT_LENGTH_SIZE: u32 = 2; +// global MAX_PRIVATE_LOG_PLAINTEXT_SIZE_IN_BYTES: u32 = +// ENCRYPTED_PAYLOAD_SIZE_IN_BYTES - OVERHEAD_SIZE - PLAINTEXT_LENGTH_SIZE - 1 /* aes padding */; + +global BODY_SIZE: u32 = + ENCRYPTED_PAYLOAD_SIZE_IN_BYTES - EPH_PK_SIZE - HEADER_SIZE - OVERHEAD_PADDING; + +fn main( + eph_pk_bytes: [u8; EPH_PK_SIZE], + incoming_header_ciphertext: [u8; HEADER_SIZE], + incoming_body_ciphertext: [u8; BODY_SIZE], + flag: bool, +) -> pub [u8; ENCRYPTED_PAYLOAD_SIZE_IN_BYTES] { + compute_encrypted_log( + eph_pk_bytes, + incoming_header_ciphertext, + incoming_body_ciphertext, + flag, + ) +} + +fn compute_encrypted_log( + eph_pk_bytes: [u8; EPH_PK_SIZE], + incoming_header_ciphertext: [u8; HEADER_SIZE], + incoming_body_ciphertext: [u8; BODY_SIZE], + flag: bool, +) -> [u8; M] { + let mut encrypted_bytes = [0; M]; + let mut offset = 0; + + // NOTE: Adding a conditional variable can result in the array being fully copied, item by item, + // in each iteration in the second loop that copies incoming_body_ciphertext into encrypted_bytes. + // Depending on where we place the `flag` we either get the item-by-item copying (blowup), + // or just a single array item gets read and a new array constructed in each iteration (no blowup). + + // If the `flag` is here then it blows up. + if flag { + // eph_pk + for i in 0..EPH_PK_SIZE { + encrypted_bytes[offset + i] = eph_pk_bytes[i]; + } + offset += EPH_PK_SIZE; + + // If the `flag` is here then it blows up. + // if flag { + + // incoming_header + for i in 0..HEADER_SIZE { + encrypted_bytes[offset + i] = incoming_header_ciphertext[i]; + } + offset += HEADER_SIZE; + + // Padding. + offset += OVERHEAD_PADDING; + + // If the `flag` is here then it does not blow up. + //if flag { + // incoming_body + // Then we fill in the rest as the incoming body ciphertext + let size = M - offset; + + // NOTE: This made the bytecode size blowup disappear in aztec packages, + // but in this reproduction the size seems to be statically known regardless. + // let size = M - 32 - HEADER_SIZE - OVERHEAD_PADDING; + + assert_eq(size, incoming_body_ciphertext.len(), "ciphertext length mismatch"); + for i in 0..size { + encrypted_bytes[offset + i] = incoming_body_ciphertext[i]; + } + } + + encrypted_bytes +} diff --git a/test_programs/execution_success/field_attribute/Nargo.toml b/test_programs/execution_success/field_attribute/Nargo.toml new file mode 100644 index 00000000000..37487d0043c --- /dev/null +++ b/test_programs/execution_success/field_attribute/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "field_attribute" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/field_attribute/Prover.toml b/test_programs/execution_success/field_attribute/Prover.toml new file mode 100644 index 00000000000..07890234a19 --- /dev/null +++ b/test_programs/execution_success/field_attribute/Prover.toml @@ -0,0 +1 @@ +x = "3" diff --git a/test_programs/execution_success/field_attribute/src/main.nr b/test_programs/execution_success/field_attribute/src/main.nr new file mode 100644 index 00000000000..dda83db40de --- /dev/null +++ b/test_programs/execution_success/field_attribute/src/main.nr @@ -0,0 +1,19 @@ +// Test integer addition: 3 + 4 = 7 +fn main(mut x: u32) { + assert(x > foo()); +} + +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} diff --git a/test_programs/execution_success/fmtstr_with_global/Nargo.toml b/test_programs/execution_success/fmtstr_with_global/Nargo.toml new file mode 100644 index 00000000000..889683f7410 --- /dev/null +++ b/test_programs/execution_success/fmtstr_with_global/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fmtstr_with_global" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/execution_success/fmtstr_with_global/src/main.nr b/test_programs/execution_success/fmtstr_with_global/src/main.nr new file mode 100644 index 00000000000..4ca118f856f --- /dev/null +++ b/test_programs/execution_success/fmtstr_with_global/src/main.nr @@ -0,0 +1,5 @@ +global FOO: Field = 1; + +fn main() { + println(f"foo = {FOO}"); +} diff --git a/test_programs/execution_success/fold_2_to_17/Nargo.toml b/test_programs/execution_success/fold_2_to_17/Nargo.toml new file mode 100644 index 00000000000..54e4c9a64e8 --- /dev/null +++ b/test_programs/execution_success/fold_2_to_17/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_2_to_17" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/fold_2_to_17/Prover.toml b/test_programs/execution_success/fold_2_to_17/Prover.toml new file mode 100644 index 00000000000..a56a84e61a4 --- /dev/null +++ b/test_programs/execution_success/fold_2_to_17/Prover.toml @@ -0,0 +1 @@ +x = "2" diff --git a/test_programs/execution_success/fold_2_to_17/src/main.nr b/test_programs/execution_success/fold_2_to_17/src/main.nr new file mode 100644 index 00000000000..d54dff4617a --- /dev/null +++ b/test_programs/execution_success/fold_2_to_17/src/main.nr @@ -0,0 +1,16 @@ +use std::hash::poseidon2; + +global len: u32 = 2450 * 2 - 240; // for just under 2^17 gates +fn main(x: Field) { + let ped_input = [x; len]; + let mut val = poseidon2::Poseidon2::hash(ped_input, len); + let z = foo(x); + assert(val == z); +} + +#[fold] +fn foo(x: Field) -> Field { + let ped_input = [x; len]; + let mut val = poseidon2::Poseidon2::hash(ped_input, len); + val +} 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/execution_success/fold_after_inlined_calls/Prover.toml b/test_programs/execution_success/fold_after_inlined_calls/Prover.toml new file mode 100644 index 00000000000..4dd6b405159 --- /dev/null +++ b/test_programs/execution_success/fold_after_inlined_calls/Prover.toml @@ -0,0 +1 @@ +x = "1" 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/execution_success/fold_basic/Prover.toml b/test_programs/execution_success/fold_basic/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/fold_basic/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" 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..440779d2460 --- /dev/null +++ b/test_programs/execution_success/fold_basic/src/main.nr @@ -0,0 +1,13 @@ +fn main(x: Field, y: pub Field) { + let z = foo(x, y); + let z2 = foo(x, y); + let z3 = foo(x, y); + assert(z == z2); + assert(z2 == z3); +} + +#[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..5b9a5db62c5 --- /dev/null +++ b/test_programs/execution_success/fold_call_witness_condition/src/main.nr @@ -0,0 +1,16 @@ +global NUM_RESULTS: u32 = 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..b433c8b416c --- /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/fold_fibonacci/Prover.toml b/test_programs/execution_success/fold_fibonacci/Prover.toml new file mode 100644 index 00000000000..3a627b9188b --- /dev/null +++ b/test_programs/execution_success/fold_fibonacci/Prover.toml @@ -0,0 +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..15b9dd26195 --- /dev/null +++ b/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr @@ -0,0 +1,33 @@ +use std::hash::poseidon2::Poseidon2; + +global NUM_HASHES: u32 = 2; +global HASH_LENGTH: u32 = 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/Nargo.toml b/test_programs/execution_success/generics/Nargo.toml new file mode 100644 index 00000000000..19c8ff28ec7 --- /dev/null +++ b/test_programs/execution_success/generics/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "generics" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/generics/Prover.toml b/test_programs/execution_success/generics/Prover.toml new file mode 100644 index 00000000000..85f1e9f96f2 --- /dev/null +++ b/test_programs/execution_success/generics/Prover.toml @@ -0,0 +1,2 @@ +x = "2" +y = "2" diff --git a/test_programs/execution_success/generics/src/main.nr b/test_programs/execution_success/generics/src/main.nr new file mode 100644 index 00000000000..329759caea0 --- /dev/null +++ b/test_programs/execution_success/generics/src/main.nr @@ -0,0 +1,82 @@ +struct Bar { + one: Field, + two: Field, + other: T, +} + +fn foo(bar: Bar) { + assert(bar.one == bar.two); +} + +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 + } +} + +impl Bar { + fn get_other(self) -> Field { + self.other + } +} + +impl Bar { + // This is to test that we can use turbofish on methods as well + fn zeroed(_self: Self) -> A { + std::mem::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] }; + + foo(bar1); + foo(bar2); + // Test generic impls + let int1 = BigInt { limbs: [1] }; + let int2 = BigInt { limbs: [2] }; + let BigInt { limbs } = int1.second(int2).first(int1); + assert(limbs == int2.limbs); + // Test impl exclusively for Bar + assert(bar1.get_other() == bar1.other); + // Expected type error + // assert(bar2.get_other() == bar2.other); + let one = x; + let two = y; + 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]); +} + +fn regression_2055(bytes: [u8; LEN]) -> Field { + let mut f = 0; + let mut b = 1; + let mut len = LEN - 1; // FAILS + for i in 0..LEN { + let j = len - i; + f += (bytes[j] as Field) * b; + b *= 256; + } + f +} diff --git a/test_programs/execution_success/global_consts/Nargo.toml b/test_programs/execution_success/global_consts/Nargo.toml new file mode 100644 index 00000000000..3b4d6be2353 --- /dev/null +++ b/test_programs/execution_success/global_consts/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "global_consts" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/global_consts/Prover.toml b/test_programs/execution_success/global_consts/Prover.toml new file mode 100644 index 00000000000..66f7feb1dda --- /dev/null +++ b/test_programs/execution_success/global_consts/Prover.toml @@ -0,0 +1,4 @@ +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 = [44,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] +c = [3, 3, 3] +d = [5, 5, 5, 5, 5] \ No newline at end of file diff --git a/test_programs/execution_success/global_consts/src/baz.nr b/test_programs/execution_success/global_consts/src/baz.nr new file mode 100644 index 00000000000..384cf9d3569 --- /dev/null +++ b/test_programs/execution_success/global_consts/src/baz.nr @@ -0,0 +1,5 @@ +pub fn from_baz(x: [Field; crate::foo::MAGIC_NUMBER]) { + for i in 0..crate::foo::MAGIC_NUMBER { + assert(x[i] == crate::foo::MAGIC_NUMBER as Field); + } +} diff --git a/test_programs/execution_success/global_consts/src/foo.nr b/test_programs/execution_success/global_consts/src/foo.nr new file mode 100644 index 00000000000..2c39b534259 --- /dev/null +++ b/test_programs/execution_success/global_consts/src/foo.nr @@ -0,0 +1,11 @@ +mod bar; + +global N: u32 = 5; +global MAGIC_NUMBER: u32 = 3; +global TYPE_INFERRED: u32 = 42; + +pub fn from_foo(x: [Field; bar::N]) { + for i in 0..bar::N { + assert(x[i] == bar::N as Field); + } +} diff --git a/test_programs/execution_success/global_consts/src/foo/bar.nr b/test_programs/execution_success/global_consts/src/foo/bar.nr new file mode 100644 index 00000000000..61ac1e8e8ed --- /dev/null +++ b/test_programs/execution_success/global_consts/src/foo/bar.nr @@ -0,0 +1,5 @@ +global N: u32 = 5; + +pub fn from_bar(x: Field) -> Field { + x * N as Field +} diff --git a/test_programs/execution_success/global_consts/src/main.nr b/test_programs/execution_success/global_consts/src/main.nr new file mode 100644 index 00000000000..9f84af35cba --- /dev/null +++ b/test_programs/execution_success/global_consts/src/main.nr @@ -0,0 +1,124 @@ +mod foo; +mod baz; + +global M: u32 = 32; +global L: Field = 10; // Unused globals currently allowed +global N: u32 = 5; +global T_LEN: u32 = 2; + +// Globals can reference other globals +global DERIVED: Field = M as Field + L; + +struct Dummy { + x: [Field; N], + y: [Field; foo::MAGIC_NUMBER], +} + +struct Test { + v: Field, +} +global VALS: [Test; 1] = [Test { v: 100 }]; +global NESTED: [[Test; 1]; 2] = [VALS, VALS]; + +unconstrained fn calculate_global_value() -> Field { + 42 +} + +// Regression test for https://github.com/noir-lang/noir/issues/4318 +global CALCULATED_GLOBAL: Field = calculate_global_value(); + +fn main( + a: [Field; M + N - N], + b: [Field; 30 + N / 2], + c: pub [Field; foo::MAGIC_NUMBER], + d: [Field; foo::bar::N], +) { + let test_struct = Dummy { x: d, y: c }; + + for i in 0..foo::MAGIC_NUMBER { + assert(c[i] == foo::MAGIC_NUMBER as Field); + assert(test_struct.y[i] == foo::MAGIC_NUMBER as Field); + assert(test_struct.y[i] != NESTED[1][0].v); + } + + assert(N as Field != M as Field); + + let expected: u32 = 42; + assert(foo::TYPE_INFERRED == expected); + + let mut y = 5; + let mut x = M; + for i in 0..N * N { + let M: u32 = 10; + x = M; + + y = i; + } + assert(y == 24); + assert(x == 10); + + let q = multiplyByM(3); + assert(q == 96); + + arrays_neq(a, b); + + let t: [Field; T_LEN] = [N as Field, M as Field]; + assert(t[1] == 32); + + assert(15 == my_submodule::my_helper()); + + let add_submodules_N = my_submodule::N as Field + foo::bar::N as Field; + assert(15 == add_submodules_N); + let add_from_bar_N = my_submodule::N as Field + foo::bar::from_bar(1); + assert(15 == add_from_bar_N); + // Example showing an array filled with (my_submodule::N + 2) 0's + let sugared = [0; my_submodule::N + 2]; + assert(sugared[my_submodule::N + 1] == 0); + + let arr: [Field; my_submodule::N] = [N as Field; 10]; + assert((arr[0] == 5) & (arr[9] == 5)); + + foo::from_foo(d); + baz::from_baz(c); + assert(DERIVED == M as Field + L); + + assert(CALCULATED_GLOBAL == 42); +} + +fn multiplyByM(x: Field) -> Field { + x * M as Field +} + +fn arrays_neq(a: [Field; M], b: [Field; M]) { + assert(a != b); +} + +mod my_submodule { + global N: u32 = 10; + global L: Field = 50; + + fn my_bool_or(x: u1, y: u1) { + assert(x | y == 1); + } + + pub fn my_helper() -> Field { + let N: u32 = 15; // Like in Rust, local variables override globals + let x = N as Field; + x + } +} + +struct Foo { + a: Field, +} + +struct Bar {} + +impl Bar { + fn get_a() -> Field { + 1 + } +} + +// Regression for #1440 +global foo: Foo = Foo { a: Bar::get_a() }; diff --git a/test_programs/execution_success/global_var_regression_simple/Nargo.toml b/test_programs/execution_success/global_var_regression_simple/Nargo.toml new file mode 100644 index 00000000000..50b4902de22 --- /dev/null +++ b/test_programs/execution_success/global_var_regression_simple/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "global_var_regression_simple" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/global_var_regression_simple/Prover.toml b/test_programs/execution_success/global_var_regression_simple/Prover.toml new file mode 100644 index 00000000000..2c1854573a4 --- /dev/null +++ b/test_programs/execution_success/global_var_regression_simple/Prover.toml @@ -0,0 +1,2 @@ +x = 1 +y = 2 diff --git a/test_programs/execution_success/global_var_regression_simple/src/main.nr b/test_programs/execution_success/global_var_regression_simple/src/main.nr new file mode 100644 index 00000000000..b1bf753a73c --- /dev/null +++ b/test_programs/execution_success/global_var_regression_simple/src/main.nr @@ -0,0 +1,25 @@ +global EXPONENTIATE: [[Field; 2]; 2] = [[1, 1], [0, 0]]; + +fn main(x: Field, y: pub Field) { + let mut acc: Field = 0; + for i in 0..2 { + for j in 0..2 { + acc += EXPONENTIATE[i][j]; + } + } + assert(!acc.lt(x)); + assert(x != y); + + dummy_again(x, y); +} + +fn dummy_again(x: Field, y: Field) { + let mut acc: Field = 0; + for i in 0..2 { + for j in 0..2 { + acc += EXPONENTIATE[i][j]; + } + } + assert(!acc.lt(x)); + assert(x != y); +} diff --git a/test_programs/execution_success/hash_to_field/Nargo.toml b/test_programs/execution_success/hash_to_field/Nargo.toml new file mode 100644 index 00000000000..a00a7bdc050 --- /dev/null +++ b/test_programs/execution_success/hash_to_field/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "hash_to_field" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/hash_to_field/Prover.toml b/test_programs/execution_success/hash_to_field/Prover.toml new file mode 100644 index 00000000000..f6597d3f78a --- /dev/null +++ b/test_programs/execution_success/hash_to_field/Prover.toml @@ -0,0 +1 @@ +input = "1" diff --git a/test_programs/execution_success/hash_to_field/src/main.nr b/test_programs/execution_success/hash_to_field/src/main.nr new file mode 100644 index 00000000000..bb4f829ec33 --- /dev/null +++ b/test_programs/execution_success/hash_to_field/src/main.nr @@ -0,0 +1,3 @@ +fn main(input: Field) -> pub Field { + std::hash::hash_to_field(&[input]) +} diff --git a/test_programs/execution_success/hashmap/Nargo.toml b/test_programs/execution_success/hashmap/Nargo.toml new file mode 100644 index 00000000000..c09debc9833 --- /dev/null +++ b/test_programs/execution_success/hashmap/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "hashmap" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/hashmap/Prover.toml b/test_programs/execution_success/hashmap/Prover.toml new file mode 100644 index 00000000000..84d4c0733e4 --- /dev/null +++ b/test_programs/execution_success/hashmap/Prover.toml @@ -0,0 +1,26 @@ +# Input: 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/execution_success/hashmap/src/main.nr b/test_programs/execution_success/hashmap/src/main.nr new file mode 100644 index 00000000000..aab531ea559 --- /dev/null +++ b/test_programs/execution_success/hashmap/src/main.nr @@ -0,0 +1,356 @@ +mod utils; + +use std::collections::map::HashMap; +use std::hash::BuildHasherDefault; +use std::hash::poseidon2::Poseidon2Hasher; + +use utils::cut; + +type K = Field; +type V = Field; + +// It is more convenient and readable to use structs as input. +struct Entry { + key: Field, + value: Field, +} + +global HASHMAP_CAP: u32 = 8; +global HASHMAP_LEN: u32 = 6; + +global FIELD_CMP: fn(Field, Field) -> bool = |a: Field, b: Field| a.lt(b); + +global K_CMP: fn(Field, Field) -> bool = FIELD_CMP; +global V_CMP: fn(Field, Field) -> bool = FIELD_CMP; +global KV_CMP: fn((K, V), (K, V)) -> bool = |a: (K, V), b: (K, V)| a.0.lt(b.0); + +global ALLOCATE_HASHMAP: fn() -> HashMap> = + || -> HashMap> HashMap::default(); + +fn main(input: [Entry; HASHMAP_LEN]) { + test_sequential(input[0].key, input[0].value); + test_multiple_equal_insert(input[1].key, input[1].value); + test_value_override(input[2].key, input[2].value, input[3].value); + test_insert_and_methods(input); + test_hashmaps_equality(input); + test_retain(); + test_iterators(); + test_mut_iterators(); + + doc_tests(); +} + +// Insert, get, remove. +fn test_sequential(key: K, value: V) { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New HashMap should be empty."); + + hashmap.insert(key, value); + assert(hashmap.len() == 1, "HashMap after one insert should have a length of 1 element."); + + let got = hashmap.get(key); + assert(got.is_some(), "Got none value."); + let got = got.unwrap_unchecked(); + assert(value == got, f"Inserted {value} but got {got} for the same key."); + + hashmap.remove(key); + assert( + hashmap.is_empty(), + "HashMap after one insert and corresponding removal should be empty.", + ); + let got = hashmap.get(key); + assert(got.is_none(), "Value has been removed, but is still available (not none)."); +} + +// Insert same pair several times. +fn test_multiple_equal_insert(key: K, value: V) { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New HashMap should be empty."); + + for _ in 0..HASHMAP_LEN { + hashmap.insert(key, value); + } + + let len = hashmap.len(); + assert(len == 1, f"HashMap length must be 1, got {len}."); + + let got = hashmap.get(key); + assert(got.is_some(), "Got none value."); + let got = got.unwrap_unchecked(); + assert(value == got, f"Inserted {value} but got {got} for the same key."); +} + +// Override value for existing pair. +fn test_value_override(key: K, value: V, new_value: V) { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New hashmap should be empty."); + + hashmap.insert(key, value); + hashmap.insert(key, new_value); + assert(hashmap.len() == 1, "HashMap length is invalid."); + + let got = hashmap.get(key); + assert(got.is_some(), "Got none value."); + let got = got.unwrap_unchecked(); + assert(got == new_value, f"Expected {new_value}, but got {got}."); +} + +// Insert several distinct pairs and test auxiliary methods. +fn test_insert_and_methods(input: [Entry; HASHMAP_LEN]) { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New HashMap should be empty."); + + for entry in input { + hashmap.insert(entry.key, entry.value); + } + + assert(hashmap.len() == HASHMAP_LEN, "hashmap.len() does not match input length."); + + for entry in input { + let entry_key = entry.key; + assert(hashmap.contains_key(entry.key), f"Not found inserted key {entry_key}."); + } + + hashmap.clear(); + assert(hashmap.is_empty(), "HashMap after clear() should be empty."); +} + +// Insert several pairs and test retaining. +fn test_retain() { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New HashMap should be empty."); + + let (key, value) = (5, 11); + hashmap.insert(key, value); + let (key, value) = (2, 13); + hashmap.insert(key, value); + let (key, value) = (11, 5); + hashmap.insert(key, value); + + let predicate = |key: K, value: V| -> bool { key * value == 55 }; + hashmap.retain(predicate); + + assert(hashmap.len() == 2, "HashMap should have retained 2 elements."); + assert( + hashmap.get(2).is_none(), + "Pair should have been removed, since it does not match predicate.", + ); +} + +// Equality trait check. +fn test_hashmaps_equality(input: [Entry; HASHMAP_LEN]) { + let mut hashmap_1 = ALLOCATE_HASHMAP(); + let mut hashmap_2 = ALLOCATE_HASHMAP(); + + for entry in input { + hashmap_1.insert(entry.key, entry.value); + hashmap_2.insert(entry.key, entry.value); + } + + assert(hashmap_1 == hashmap_2, "HashMaps should be equal."); + + hashmap_2.remove(input[0].key); + + assert(hashmap_1 != hashmap_2, "HashMaps should not be equal."); +} + +// Test entries, keys, values. +fn test_iterators() { + let mut hashmap = ALLOCATE_HASHMAP(); + + hashmap.insert(2, 3); + hashmap.insert(5, 7); + hashmap.insert(11, 13); + + 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."); + assert(entries == [(2, 3), (5, 7), (11, 13)], "Got incorrect iteration of entries."); +} + +// Test mutable iteration over keys, values and entries. +fn test_mut_iterators() { + let mut hashmap = ALLOCATE_HASHMAP(); + + hashmap.insert(2, 3); + hashmap.insert(5, 7); + hashmap.insert(11, 13); + + let f = |k: K| -> K { k * 3 }; + hashmap.iter_keys_mut(f); + + let f = |v: V| -> V { v * 5 }; + hashmap.iter_values_mut(f); + + 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."); + + let f = |k: K, v: V| -> (K, V) { (k * 2, v * 2) }; + hashmap.iter_mut(f); + + 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 new file mode 100644 index 00000000000..de6c78f5adf --- /dev/null +++ b/test_programs/execution_success/hashmap/src/utils.nr @@ -0,0 +1,10 @@ +// 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 = BoundedVec::new(); + for i in 0..M { + new.push(input.get(i)); + } + new.storage() +} diff --git a/test_programs/execution_success/higher_order_functions/Nargo.toml b/test_programs/execution_success/higher_order_functions/Nargo.toml new file mode 100644 index 00000000000..8f8a79e7e83 --- /dev/null +++ b/test_programs/execution_success/higher_order_functions/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "higher_order_functions" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/higher_order_functions/Prover.toml b/test_programs/execution_success/higher_order_functions/Prover.toml new file mode 100644 index 00000000000..b373bb827c4 --- /dev/null +++ b/test_programs/execution_success/higher_order_functions/Prover.toml @@ -0,0 +1 @@ +w = 1 \ No newline at end of file diff --git a/test_programs/execution_success/higher_order_functions/src/main.nr b/test_programs/execution_success/higher_order_functions/src/main.nr new file mode 100644 index 00000000000..1f9598f8591 --- /dev/null +++ b/test_programs/execution_success/higher_order_functions/src/main.nr @@ -0,0 +1,94 @@ +fn main(w: Field) -> pub Field { + let f = if 3 * 7 > 200 as u32 { foo } else { bar }; + assert(f()[1] == 2); + // Lambdas: + assert(twice(|x| x * 2, 5) == 20); + assert((|x, y| x + y + 1)(2, 3) == 6); + // nested lambdas + assert((|a, b| a + (|c| c + 2)(b))(0, 1) == 3); + // Closures: + let a = 42; + let g = || a; + assert(g() == 42); + // When you copy mutable variables, + // the capture of the copies shouldn't change: + let mut x = 2; + x = x + 1; + let z = x; + // Add extra mutations to ensure we can mutate x without the + // captured z changing. + x = x + 1; + assert((|y| y + z)(1) == 4); + // When you capture mutable variables, + // again, the captured variable doesn't change: + let closure_capturing_mutable = (|y| y + x); + assert(closure_capturing_mutable(1) == 5); + x += 1; + assert(closure_capturing_mutable(1) == 5); + + regression_2154(); + + let ret = twice(add1, 3); + + test_array_functions(); + w + ret +} +/// Test the array functions in std::array +fn test_array_functions() { + let two = 2; // giving this a name, to ensure that the Option functions work with closures + let myarray: [i32; 3] = [1, 2, 3]; + assert(myarray.any(|n| n > 2)); + assert(myarray.any(|n| n > two)); + + let evens: [i32; 3] = myarray.map(|n| n * two); // [2, 4, 6] + assert(evens.all(|n| n > 1)); + assert(evens.all(|n| n >= two)); + + assert(evens.fold(0, |a, b| a + b) == 12); + assert(evens.fold(0, |a, b| a + b + two) == 18); + assert(evens.reduce(|a, b| a + b) == 12); + assert(evens.reduce(|a, b| a + b + two) == 16); + // TODO: is this a sort_via issue with the new backend, + // or something more general? + // + // currently it fails only with `--experimental-ssa` with + // "not yet implemented: Cast into signed" + // but it worked with the original ssa backend + // (before dropping it) + // + // opened #2121 for it + // https://github.com/noir-lang/noir/issues/2121 + // let descending = myarray.sort_via(|a, b| a >= b); + // assert(descending == [3, 2, 1]); + assert(evens.map(|n| n / 2) == myarray); + assert(evens.map(|n| n / two) == myarray); +} + +fn foo() -> [u32; 2] { + [1, 3] +} + +fn bar() -> [u32; 2] { + [3, 2] +} + +fn add1(x: Field) -> Field { + x + 1 +} + +fn twice(f: fn(Field) -> Field, x: Field) -> Field { + f(f(x)) +} +// Fixing an ICE, where rewriting the closures +// during monomorphization didn't correspond +// to an internal `if` type +// found by @jfecher: +// https://github.com/noir-lang/noir/pull/1959#issuecomment-1658992989 +// issue https://github.com/noir-lang/noir/issues/2154 +fn regression_2154() { + let x: u32 = 32; + + let closure_if_else = if x > 2 { || x } else { || x + 2342 }; + + assert(closure_if_else() == 32); +} diff --git a/test_programs/execution_success/hint_black_box/Nargo.toml b/test_programs/execution_success/hint_black_box/Nargo.toml new file mode 100644 index 00000000000..8a49ec25494 --- /dev/null +++ b/test_programs/execution_success/hint_black_box/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "hint_black_box" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/hint_black_box/Prover.toml b/test_programs/execution_success/hint_black_box/Prover.toml new file mode 100644 index 00000000000..67dda9c2b68 --- /dev/null +++ b/test_programs/execution_success/hint_black_box/Prover.toml @@ -0,0 +1,3 @@ +# 5 * a = b +a = 10 +b = 50 diff --git a/test_programs/execution_success/hint_black_box/src/main.nr b/test_programs/execution_success/hint_black_box/src/main.nr new file mode 100644 index 00000000000..abceadb07ff --- /dev/null +++ b/test_programs/execution_success/hint_black_box/src/main.nr @@ -0,0 +1,91 @@ +use std::hint::black_box; + +fn main(a: u32, b: u32) { + // This version unrolls into a number of additions + assert_eq(loop(5, a), b); + // This version simplifies into a single `constraint 50 == b` + assert_eq(loop(5, 10), b); + // This version should not simplify down to a single constraint, + // it should treat 10 as opaque: + assert_eq(loop(5, black_box(10)), b); + + // Check array handling. + let arr = [a, a, a, a, a]; + + assert_eq(array_sum(arr), b); + assert_eq(array_sum(black_box(arr)), b); + + assert_eq(slice_sum(arr.as_slice()), b); + assert_eq(slice_sum(black_box(arr).as_slice()), b); + + // This doesn't work because by calling `black_box` on a slice the compiler + // loses track of the length, and then cannot unroll the loop for ACIR. + //assert_eq(slice_sum(black_box(arr.as_slice())), b); + + // But we can pass a blackboxed slice to Brillig. + /// Safety: testing context + let s = unsafe { brillig_slice_sum(black_box(arr.as_slice())) }; + assert_eq(s, b); + + let mut d = b; + // This gets completely eliminated: + let mut c = 0; + set_ref(&mut c, &mut d); + assert_eq(c, b); + + // This way the constraint is preserved: + let mut c = 0; + set_ref(&mut c, &mut black_box(d)); + assert_eq(c, b); + + // A reference over the output of black box is not the original variable: + let mut c = 0; + set_ref(&mut black_box(c), &mut d); + assert_eq(c, 0); + + // This would cause a causes a crash during SSA passes unless it's a Brillig runtime: + // > Could not resolve some references to the array. All references must be resolved at compile time + // The SSA cannot have Allocate by the time we start generating ACIR, but `black_box` prevents them + // from being optimised away during SSA passes. + // If we use `--force-brillig` then the it doesn't crash but the assertion fails because `mem2reg` + // eliminates the storing to the reference. + //let mut c = 0; + //set_ref(black_box(&mut c), black_box(&mut d)); + //assert_eq(c, b); +} + +fn loop(n: u32, k: u32) -> u32 { + let mut sum = 0; + for _ in 0..n { + sum = sum + k; + } + sum +} + +fn array_sum(xs: [u32; N]) -> u32 { + let mut sum = 0; + for i in 0..N { + sum = sum + xs[i]; + } + sum +} + +fn slice_sum(xs: [u32]) -> u32 { + let mut sum = 0; + for x in xs { + sum = sum + x; + } + sum +} + +unconstrained fn brillig_slice_sum(xs: [u32]) -> u32 { + let mut sum = 0; + for x in xs { + sum = sum + x; + } + sum +} + +fn set_ref(c: &mut u32, b: &mut u32) { + *c = *b; +} diff --git a/test_programs/execution_success/if_else_chain/Nargo.toml b/test_programs/execution_success/if_else_chain/Nargo.toml new file mode 100644 index 00000000000..2f0dc93d120 --- /dev/null +++ b/test_programs/execution_success/if_else_chain/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "if_else_chain" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/if_else_chain/Prover.toml b/test_programs/execution_success/if_else_chain/Prover.toml new file mode 100644 index 00000000000..84aeb36ac21 --- /dev/null +++ b/test_programs/execution_success/if_else_chain/Prover.toml @@ -0,0 +1,2 @@ +a=0 +c=[2, 4, 3, 0, ] diff --git a/test_programs/execution_success/if_else_chain/src/main.nr b/test_programs/execution_success/if_else_chain/src/main.nr new file mode 100644 index 00000000000..2705d5b3111 --- /dev/null +++ b/test_programs/execution_success/if_else_chain/src/main.nr @@ -0,0 +1,15 @@ +fn main(a: u32, mut c: [u32; 4]) { + if a == c[0] { + assert(c[0] == 0); + } else if a == c[1] { + assert(c[1] == 0); + } else if a == c[2] { + assert(c[2] == 0); + } else if a == c[3] { + // expect to match this case + assert(c[3] == 0); + } else { + assert(c[0] == 10); + } +} + diff --git a/test_programs/execution_success/import/Nargo.toml b/test_programs/execution_success/import/Nargo.toml new file mode 100644 index 00000000000..c92328f106c --- /dev/null +++ b/test_programs/execution_success/import/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "import" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/import/Prover.toml b/test_programs/execution_success/import/Prover.toml new file mode 100644 index 00000000000..8c12ebba6cf --- /dev/null +++ b/test_programs/execution_success/import/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "2" diff --git a/test_programs/execution_success/import/src/import.nr b/test_programs/execution_success/import/src/import.nr new file mode 100644 index 00000000000..ef3f0d94c28 --- /dev/null +++ b/test_programs/execution_success/import/src/import.nr @@ -0,0 +1,3 @@ +pub fn hello(x: Field) -> Field { + x +} diff --git a/test_programs/execution_success/import/src/main.nr b/test_programs/execution_success/import/src/main.nr new file mode 100644 index 00000000000..0f5aa7e5460 --- /dev/null +++ b/test_programs/execution_success/import/src/main.nr @@ -0,0 +1,9 @@ +mod import; +use crate::import::hello; + +fn main(x: Field, y: Field) { + let _k = std::hash::pedersen_commitment([x]); + let _l = hello(x); + + assert(x != import::hello(y)); +} diff --git a/test_programs/execution_success/inline_decompose_hint_brillig_call/Nargo.toml b/test_programs/execution_success/inline_decompose_hint_brillig_call/Nargo.toml new file mode 100644 index 00000000000..ecac2dfb197 --- /dev/null +++ b/test_programs/execution_success/inline_decompose_hint_brillig_call/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "inline_decompose_hint_brillig_call" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/inline_decompose_hint_brillig_call/src/main.nr b/test_programs/execution_success/inline_decompose_hint_brillig_call/src/main.nr new file mode 100644 index 00000000000..e500f0f976d --- /dev/null +++ b/test_programs/execution_success/inline_decompose_hint_brillig_call/src/main.nr @@ -0,0 +1,15 @@ +use std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, fixed_base_scalar_mul}; + +fn main() -> pub Field { + let pre_address = 0x23d95e303879a5d0bbef78ecbc335e559da37431f6dcd11da54ed375c2846813; + let (a, b) = std::field::bn254::decompose(pre_address); + let curve = EmbeddedCurveScalar { lo: a, hi: b }; + let key = fixed_base_scalar_mul(curve); + let point = EmbeddedCurvePoint { + x: 0x111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e, + y: 0x273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be95, + is_infinite: false, + }; + let address_point = key.add(point); + address_point.x +} 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..fbe96700abe --- /dev/null +++ b/test_programs/execution_success/inline_never_basic/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" \ No newline at end of file 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..505a1641c76 --- /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/integer_array_indexing/Nargo.toml b/test_programs/execution_success/integer_array_indexing/Nargo.toml new file mode 100644 index 00000000000..6e639b64f58 --- /dev/null +++ b/test_programs/execution_success/integer_array_indexing/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "integer_array_indexing" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/integer_array_indexing/Prover.toml b/test_programs/execution_success/integer_array_indexing/Prover.toml new file mode 100644 index 00000000000..1496028f60a --- /dev/null +++ b/test_programs/execution_success/integer_array_indexing/Prover.toml @@ -0,0 +1,2 @@ +arr = [1, 2, 3] +x = 2 diff --git a/test_programs/execution_success/integer_array_indexing/src/main.nr b/test_programs/execution_success/integer_array_indexing/src/main.nr new file mode 100644 index 00000000000..1698c68161b --- /dev/null +++ b/test_programs/execution_success/integer_array_indexing/src/main.nr @@ -0,0 +1,10 @@ +global ARRAY_LEN: u32 = 3; + +fn main(arr: [Field; ARRAY_LEN], x: u32) -> pub Field { + let mut value = arr[ARRAY_LEN - 1]; + + value += arr[0 as u32]; + value += arr[1 as Field]; + + value + x as Field +} diff --git a/test_programs/execution_success/keccak256/Nargo.toml b/test_programs/execution_success/keccak256/Nargo.toml new file mode 100644 index 00000000000..7e48c3b342c --- /dev/null +++ b/test_programs/execution_success/keccak256/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "keccak256" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/keccak256/Prover.toml b/test_programs/execution_success/keccak256/Prover.toml new file mode 100644 index 00000000000..d65c4011d3f --- /dev/null +++ b/test_programs/execution_success/keccak256/Prover.toml @@ -0,0 +1,35 @@ +x = 0xbd +result = [ + 0x5a, + 0x50, + 0x2f, + 0x9f, + 0xca, + 0x46, + 0x7b, + 0x26, + 0x6d, + 0x5b, + 0x78, + 0x33, + 0x65, + 0x19, + 0x37, + 0xe8, + 0x05, + 0x27, + 0x0c, + 0xa3, + 0xf3, + 0xaf, + 0x1c, + 0x0d, + 0xd2, + 0x46, + 0x2d, + 0xca, + 0x4b, + 0x3b, + 0x1a, + 0xbf, +] diff --git a/test_programs/execution_success/keccak256/src/main.nr b/test_programs/execution_success/keccak256/src/main.nr new file mode 100644 index 00000000000..1e13fa028b7 --- /dev/null +++ b/test_programs/execution_success/keccak256/src/main.nr @@ -0,0 +1,20 @@ +// docs:start:keccak256 +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); +} +// docs:end:keccak256 diff --git a/test_programs/execution_success/loop/Nargo.toml b/test_programs/execution_success/loop/Nargo.toml new file mode 100644 index 00000000000..66c72338363 --- /dev/null +++ b/test_programs/execution_success/loop/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "loop" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/loop/Prover.toml b/test_programs/execution_success/loop/Prover.toml new file mode 100644 index 00000000000..0f44bf96f44 --- /dev/null +++ b/test_programs/execution_success/loop/Prover.toml @@ -0,0 +1 @@ +six_as_u32 = "6" diff --git a/test_programs/execution_success/loop/src/main.nr b/test_programs/execution_success/loop/src/main.nr new file mode 100644 index 00000000000..b3be4c4c3ff --- /dev/null +++ b/test_programs/execution_success/loop/src/main.nr @@ -0,0 +1,32 @@ +// Tests a very simple program. +// +// The features being tested is basic looping. +fn main(six_as_u32: u32) { + assert_eq(loop(4), six_as_u32); + assert_eq(loop_incl(3), six_as_u32); + assert(plain_loop() == six_as_u32); +} + +fn loop(x: u32) -> u32 { + let mut sum = 0; + for i in 0..x { + sum = sum + i; + } + sum +} + +fn loop_incl(x: u32) -> u32 { + let mut sum = 0; + for i in 0..=x { + sum = sum + i; + } + sum +} + +fn plain_loop() -> u32 { + let mut sum = 0; + for i in 0..4 { + sum = sum + i; + } + sum +} diff --git a/test_programs/execution_success/loop_invariant_regression/Nargo.toml b/test_programs/execution_success/loop_invariant_regression/Nargo.toml new file mode 100644 index 00000000000..9590789f52e --- /dev/null +++ b/test_programs/execution_success/loop_invariant_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "loop_invariant_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.38.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/loop_invariant_regression/Prover.toml b/test_programs/execution_success/loop_invariant_regression/Prover.toml new file mode 100644 index 00000000000..18680c805a7 --- /dev/null +++ b/test_programs/execution_success/loop_invariant_regression/Prover.toml @@ -0,0 +1,2 @@ +x = "2" +y = "3" diff --git a/test_programs/execution_success/loop_invariant_regression/src/main.nr b/test_programs/execution_success/loop_invariant_regression/src/main.nr new file mode 100644 index 00000000000..c28ce063116 --- /dev/null +++ b/test_programs/execution_success/loop_invariant_regression/src/main.nr @@ -0,0 +1,26 @@ +// Tests a simple loop where we expect loop invariant instructions +// to be hoisted to the loop's pre-header block. +fn main(x: u32, y: u32) { + loop(4, x, y); + array_read_loop(4, x); +} + +fn loop(upper_bound: u32, x: u32, y: u32) { + for _ in 0..upper_bound { + let mut z = x * y; + z = z * x; + assert_eq(z, 12); + } +} + +fn array_read_loop(upper_bound: u32, x: u32) { + let arr = [2; 5]; + for i in 0..upper_bound { + for j in 0..upper_bound { + for _ in 0..upper_bound { + assert_eq(arr[i], x); + assert_eq(arr[j], x); + } + } + } +} diff --git a/test_programs/execution_success/main_bool_arg/Nargo.toml b/test_programs/execution_success/main_bool_arg/Nargo.toml new file mode 100644 index 00000000000..c1cedb6c657 --- /dev/null +++ b/test_programs/execution_success/main_bool_arg/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "main_bool_arg" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/main_bool_arg/Prover.toml b/test_programs/execution_success/main_bool_arg/Prover.toml new file mode 100644 index 00000000000..f932e0b4817 --- /dev/null +++ b/test_programs/execution_success/main_bool_arg/Prover.toml @@ -0,0 +1,2 @@ +x = true +y = [true, false] \ No newline at end of file diff --git a/test_programs/execution_success/main_bool_arg/src/main.nr b/test_programs/execution_success/main_bool_arg/src/main.nr new file mode 100644 index 00000000000..2c50d7dee16 --- /dev/null +++ b/test_programs/execution_success/main_bool_arg/src/main.nr @@ -0,0 +1,8 @@ +fn main(x: bool, y: [bool; 2]) { + if x { + assert(1 != 2); + } + + assert(x); + assert(y[0] != y[1]); +} diff --git a/test_programs/execution_success/main_return/Nargo.toml b/test_programs/execution_success/main_return/Nargo.toml new file mode 100644 index 00000000000..793ae612730 --- /dev/null +++ b/test_programs/execution_success/main_return/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "main_return" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/main_return/Prover.toml b/test_programs/execution_success/main_return/Prover.toml new file mode 100644 index 00000000000..63e9878811a --- /dev/null +++ b/test_programs/execution_success/main_return/Prover.toml @@ -0,0 +1 @@ +x = "8" diff --git a/test_programs/execution_success/main_return/src/main.nr b/test_programs/execution_success/main_return/src/main.nr new file mode 100644 index 00000000000..06347eb0919 --- /dev/null +++ b/test_programs/execution_success/main_return/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: pub Field) -> pub Field { + x +} diff --git a/test_programs/execution_success/merkle_insert/Nargo.toml b/test_programs/execution_success/merkle_insert/Nargo.toml new file mode 100644 index 00000000000..f09458411d8 --- /dev/null +++ b/test_programs/execution_success/merkle_insert/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "merkle_insert" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/merkle_insert/Prover.toml b/test_programs/execution_success/merkle_insert/Prover.toml new file mode 100644 index 00000000000..3248d75a9b9 --- /dev/null +++ b/test_programs/execution_success/merkle_insert/Prover.toml @@ -0,0 +1,10 @@ +old_root = "0x2131c74af6250d1246797588ff075b672e3d2e6805f9c6b313ade8f6b9e12802" +old_leaf = "0x2df8b940e5890e4e1377e05373fae69a1d754f6935e6a780b666947431f2cdcd" +old_hash_path = [ + "0x03542cb720369f19a74fd05b4edfbedb27a78514ad3283f1b3270a1656cced8e", + "0x1278272f6e617666b18c52349c4bbe94249a8ab59add2ee0a142168a92b7ffc2", + "0x2547cfd7699ad1f331fb77b30a3445c6043a4c62b5b1215356b2924607bf937b", +] +new_root = "0x25e2a8ee5b85e5b546ae27832b9b53f5fae5b371e3e7f8cddda839f41669fc68" +leaf = "0x23fe6c8f2426b793f0f156f57efbecbea52e951af761634a85e80cc1a9fb5003" +index = "0" diff --git a/test_programs/execution_success/merkle_insert/src/main.nr b/test_programs/execution_success/merkle_insert/src/main.nr new file mode 100644 index 00000000000..25a455c90b8 --- /dev/null +++ b/test_programs/execution_success/merkle_insert/src/main.nr @@ -0,0 +1,13 @@ +fn main( + old_root: Field, + old_leaf: Field, + old_hash_path: [Field; 3], + new_root: pub Field, + leaf: Field, + index: Field, +) { + assert(old_root == std::merkle::compute_merkle_root(old_leaf, index, old_hash_path)); + + let calculated_root = std::merkle::compute_merkle_root(leaf, index, old_hash_path); + assert(new_root == calculated_root); +} diff --git a/test_programs/execution_success/missing_closure_env/Nargo.toml b/test_programs/execution_success/missing_closure_env/Nargo.toml new file mode 100644 index 00000000000..284e61b1144 --- /dev/null +++ b/test_programs/execution_success/missing_closure_env/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "missing_closure_env" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/missing_closure_env/Prover.toml b/test_programs/execution_success/missing_closure_env/Prover.toml new file mode 100644 index 00000000000..2d76abaa89f --- /dev/null +++ b/test_programs/execution_success/missing_closure_env/Prover.toml @@ -0,0 +1 @@ +x = 42 diff --git a/test_programs/execution_success/missing_closure_env/src/main.nr b/test_programs/execution_success/missing_closure_env/src/main.nr new file mode 100644 index 00000000000..0bc99b0671c --- /dev/null +++ b/test_programs/execution_success/missing_closure_env/src/main.nr @@ -0,0 +1,16 @@ +fn main(x: Field) { + let x1 = &mut 42; + let set_x1 = |y| { *x1 = y; }; + + assert(*x1 == 42); + set_x1(44); + assert(*x1 == 44); + set_x1(*x1); + assert(*x1 == 44); + assert(x == 42); +} + +#[test] +fn test_main() { + main(42); +} diff --git a/test_programs/execution_success/modules/Nargo.toml b/test_programs/execution_success/modules/Nargo.toml new file mode 100644 index 00000000000..ab1d6e962d7 --- /dev/null +++ b/test_programs/execution_success/modules/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "modules" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/modules/Prover.toml b/test_programs/execution_success/modules/Prover.toml new file mode 100644 index 00000000000..c0a0cdfbeb0 --- /dev/null +++ b/test_programs/execution_success/modules/Prover.toml @@ -0,0 +1,2 @@ +x = "2" +y = "13" diff --git a/test_programs/execution_success/modules/src/foo.nr b/test_programs/execution_success/modules/src/foo.nr new file mode 100644 index 00000000000..ef3f0d94c28 --- /dev/null +++ b/test_programs/execution_success/modules/src/foo.nr @@ -0,0 +1,3 @@ +pub fn hello(x: Field) -> Field { + x +} diff --git a/test_programs/execution_success/modules/src/main.nr b/test_programs/execution_success/modules/src/main.nr new file mode 100644 index 00000000000..167f7e671a0 --- /dev/null +++ b/test_programs/execution_success/modules/src/main.nr @@ -0,0 +1,14 @@ +mod foo; +// This is a comment. +// +// `main` is the entry point to a binary +// +// You can have a `Binary` or a `Library` +// Release : 0.2 +// +// To run a proof on the command line, type `cargo run prove {proof_name}` +// +// To verify that proof, type `cargo run verify {proof_name}` +fn main(x: Field, y: pub Field) { + assert(x != foo::hello(y)); +} diff --git a/test_programs/execution_success/modules_more/Nargo.toml b/test_programs/execution_success/modules_more/Nargo.toml new file mode 100644 index 00000000000..bfcfe08fa79 --- /dev/null +++ b/test_programs/execution_success/modules_more/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "modules_more" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/modules_more/Prover.toml b/test_programs/execution_success/modules_more/Prover.toml new file mode 100644 index 00000000000..39a4ddb9d15 --- /dev/null +++ b/test_programs/execution_success/modules_more/Prover.toml @@ -0,0 +1,4 @@ + + x = "5" + y = "15" + \ No newline at end of file diff --git a/test_programs/execution_success/modules_more/src/foo.nr b/test_programs/execution_success/modules_more/src/foo.nr new file mode 100644 index 00000000000..fa531a1a2f0 --- /dev/null +++ b/test_programs/execution_success/modules_more/src/foo.nr @@ -0,0 +1,5 @@ +mod bar; + +fn hello(x: Field) -> Field { + x +} diff --git a/test_programs/execution_success/modules_more/src/foo/bar.nr b/test_programs/execution_success/modules_more/src/foo/bar.nr new file mode 100644 index 00000000000..1665f720be6 --- /dev/null +++ b/test_programs/execution_success/modules_more/src/foo/bar.nr @@ -0,0 +1,3 @@ +pub fn from_bar(x: Field) -> Field { + x +} diff --git a/test_programs/execution_success/modules_more/src/main.nr b/test_programs/execution_success/modules_more/src/main.nr new file mode 100644 index 00000000000..93b76d62845 --- /dev/null +++ b/test_programs/execution_success/modules_more/src/main.nr @@ -0,0 +1,5 @@ +mod foo; +// An example of the module system +fn main(x: Field, y: Field) { + assert(x != foo::bar::from_bar(y)); +} diff --git a/test_programs/execution_success/modulus/Nargo.toml b/test_programs/execution_success/modulus/Nargo.toml new file mode 100644 index 00000000000..256eeef058f --- /dev/null +++ b/test_programs/execution_success/modulus/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "modulus" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/modulus/Prover.toml b/test_programs/execution_success/modulus/Prover.toml new file mode 100644 index 00000000000..d435609bb1a --- /dev/null +++ b/test_programs/execution_success/modulus/Prover.toml @@ -0,0 +1,290 @@ +bn254_modulus_be_bytes = [ + 48, + 100, + 78, + 114, + 225, + 49, + 160, + 41, + 184, + 80, + 69, + 182, + 129, + 129, + 88, + 93, + 40, + 51, + 232, + 72, + 121, + 185, + 112, + 145, + 67, + 225, + 245, + 147, + 240, + 0, + 0, + 1, +] +bn254_modulus_be_bits = [ + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 1, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 0, + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 1, + 1, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 0, + 1, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 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, + 1, +] diff --git a/test_programs/execution_success/modulus/src/main.nr b/test_programs/execution_success/modulus/src/main.nr new file mode 100644 index 00000000000..36ec722a049 --- /dev/null +++ b/test_programs/execution_success/modulus/src/main.nr @@ -0,0 +1,34 @@ +fn main(bn254_modulus_be_bytes: [u8; 32], bn254_modulus_be_bits: [u1; 254]) { + let modulus_size = std::field::modulus_num_bits(); + // NOTE: The constraints used in this circuit will only work when testing nargo with the plonk bn254 backend + assert(modulus_size == 254); + + assert_reverse( + std::field::modulus_be_bytes(), + std::field::modulus_le_bytes(), + ); + + let modulus_be_byte_array = std::field::modulus_be_bytes(); + for i in 0..32 { + assert(modulus_be_byte_array[i] == bn254_modulus_be_bytes[i]); + } + let modulus_le_byte_array = std::field::modulus_le_bytes(); + for i in 0..32 { + assert(modulus_le_byte_array[i] == bn254_modulus_be_bytes[31 - i]); + } + + let modulus_be_bits = std::field::modulus_be_bits(); + for i in 0..254 { + assert(modulus_be_bits[i] == bn254_modulus_be_bits[i]); + } + let modulus_le_bits = std::field::modulus_le_bits(); + for i in 0..254 { + assert(modulus_le_bits[i] == bn254_modulus_be_bits[253 - i]); + } +} + +fn assert_reverse(forwards: [u8], backwards: [u8]) { + for i in 0..32 { + assert_eq(forwards[i], backwards[31 - i]); + } +} diff --git a/test_programs/execution_success/negated_jmpif_condition/Nargo.toml b/test_programs/execution_success/negated_jmpif_condition/Nargo.toml new file mode 100644 index 00000000000..c83e2c1c1fd --- /dev/null +++ b/test_programs/execution_success/negated_jmpif_condition/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "negated_jmpif_condition" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/negated_jmpif_condition/Prover.toml b/test_programs/execution_success/negated_jmpif_condition/Prover.toml new file mode 100644 index 00000000000..151faa5a9b1 --- /dev/null +++ b/test_programs/execution_success/negated_jmpif_condition/Prover.toml @@ -0,0 +1 @@ +x = "2" \ No newline at end of file diff --git a/test_programs/execution_success/negated_jmpif_condition/src/main.nr b/test_programs/execution_success/negated_jmpif_condition/src/main.nr new file mode 100644 index 00000000000..06de2b41820 --- /dev/null +++ b/test_programs/execution_success/negated_jmpif_condition/src/main.nr @@ -0,0 +1,9 @@ +fn main(mut x: Field) { + let mut q = 0; + + if x != 10 { + q = 2; + } + + assert(q == 2); +} diff --git a/test_programs/execution_success/nested_array_dynamic/Nargo.toml b/test_programs/execution_success/nested_array_dynamic/Nargo.toml new file mode 100644 index 00000000000..72642bebc15 --- /dev/null +++ b/test_programs/execution_success/nested_array_dynamic/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "nested_array_dynamic" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/nested_array_dynamic/Prover.toml b/test_programs/execution_success/nested_array_dynamic/Prover.toml new file mode 100644 index 00000000000..6c7e77b581d --- /dev/null +++ b/test_programs/execution_success/nested_array_dynamic/Prover.toml @@ -0,0 +1,29 @@ +y = "3" + +[[x]] +a = "1" +b = ["2", "3", "20"] + +[x.bar] +inner = ["100", "101", "102"] + +[[x]] +a = "4" # idx = 3, flattened start idx = 7 +b = ["5", "6", "21"] # idx = 4, flattened start idx = 8 + +[x.bar] +inner = ["103", "104", "105"] # idx = 5, flattened start idx = 11 + +[[x]] +a = "7" +b = ["8", "9", "22"] + +[x.bar] +inner = ["106", "107", "108"] + +[[x]] +a = "10" # idx = 9, flattened start idx = 21 +b = ["11", "12", "23"] # idx = 10, flattened start idx = 22 + +[x.bar] +inner = ["109", "110", "111"] # idx = 11, flattened start idx = 25 diff --git a/test_programs/execution_success/nested_array_dynamic/src/main.nr b/test_programs/execution_success/nested_array_dynamic/src/main.nr new file mode 100644 index 00000000000..2c53822d6b9 --- /dev/null +++ b/test_programs/execution_success/nested_array_dynamic/src/main.nr @@ -0,0 +1,76 @@ +struct Bar { + inner: [Field; 3], +} + +struct Foo { + a: Field, + b: [Field; 3], + bar: Bar, +} + +struct FooParent { + array: [Field; 3], + foos: [Foo; 4], +} + +fn main(mut x: [Foo; 4], y: pub Field) { + assert(x[y - 3].a == 1); + assert(x[y - 3].b == [2, 3, 20]); + assert(x[y - 2].a == 4); + assert(x[y - 2].b == [5, 6, 21]); + assert(x[y - 1].a == 7); + assert(x[y - 1].b == [8, 9, 22]); + assert(x[y].a == 10); + assert(x[y].b == [11, 12, 23]); + assert(x[y].bar.inner == [109, 110, 111]); + // Check dynamic array set + if y != 2 { + x[y].a = 50; + } else { + x[y].a = 100; + } + assert(x[3].a == 50); + + if y == 2 { + x[y - 1].b = [50, 51, 52]; + } else { + x[y - 1].b = [100, 101, 102]; + } + assert(x[2].b == [100, 101, 102]); + + assert(x[y - 3].bar.inner == [100, 101, 102]); + assert(x[y - 2].bar.inner == [103, 104, 105]); + assert(x[y - 1].bar.inner == [106, 107, 108]); + assert(x[y].bar.inner == [109, 110, 111]); + + let foo_parent_one = FooParent { array: [0, 1, 2], foos: x }; + let foo_parent_two = FooParent { array: [3, 4, 5], foos: x }; + let mut foo_parents = [foo_parent_one, foo_parent_two]; + + assert(foo_parents[y - 3].foos[y - 3].b == [2, 3, 20]); + assert(foo_parents[y - 3].foos[y - 2].b == [5, 6, 21]); + assert(foo_parents[y - 3].foos[y - 1].b == [100, 101, 102]); + assert(foo_parents[y - 3].foos[y].b == [11, 12, 23]); + + assert(foo_parents[y - 3].foos[y].a == 50); + + assert(foo_parents[1].foos[1].b == [5, 6, 21]); + if y == 2 { + foo_parents[y - 2].foos[y - 2].b = [10, 9, 8]; + } else { + foo_parents[y - 2].foos[y - 2].b = [20, 19, 18]; + } + assert(foo_parents[1].foos[1].b == [20, 19, 18]); + + assert(foo_parents[1].foos[1].b[2] == 18); + if y == 3 { + foo_parents[y - 2].foos[y - 2].b[y - 1] = 5000; + } else { + foo_parents[y - 2].foos[y - 2].b[y - 1] = 1000; + } + assert(foo_parents[1].foos[1].b[2] == 5000); + // Set a dynamic array value + foo_parents[y - 2].foos[y - 3].b = foo_parents[y - 2].foos[y - 2].b; + assert(foo_parents[1].foos[0].b == [20, 19, 5000]); +} + diff --git a/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/nested_array_dynamic_simple/Prover.toml b/test_programs/execution_success/nested_array_dynamic_simple/Prover.toml new file mode 100644 index 00000000000..07890234a19 --- /dev/null +++ b/test_programs/execution_success/nested_array_dynamic_simple/Prover.toml @@ -0,0 +1 @@ +x = "3" 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/Nargo.toml b/test_programs/execution_success/nested_array_in_slice/Nargo.toml new file mode 100644 index 00000000000..4f0748f79be --- /dev/null +++ b/test_programs/execution_success/nested_array_in_slice/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "nested_array_in_slice" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/nested_array_in_slice/Prover.toml b/test_programs/execution_success/nested_array_in_slice/Prover.toml new file mode 100644 index 00000000000..7127baac5bf --- /dev/null +++ b/test_programs/execution_success/nested_array_in_slice/Prover.toml @@ -0,0 +1 @@ +y = "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 new file mode 100644 index 00000000000..0890115e95a --- /dev/null +++ b/test_programs/execution_success/nested_array_in_slice/src/main.nr @@ -0,0 +1,49 @@ +struct Bar { + inner: [Field; 3], +} + +struct Foo { + a: Field, + b: [Field; 3], + bar: Bar, +} + +fn main(y: Field) { + let foo_one = Foo { a: 1, b: [2, 3, 20], bar: Bar { inner: [100, 101, 102] } }; + let foo_two = Foo { a: 4, b: [5, 6, 21], bar: Bar { inner: [103, 104, 105] } }; + let foo_three = Foo { a: 7, b: [8, 9, 22], bar: Bar { inner: [106, 107, 108] } }; + let foo_four = Foo { a: 10, b: [11, 12, 23], bar: Bar { inner: [109, 110, 111] } }; + let mut x = &[foo_one]; + x = x.push_back(foo_two); + x = x.push_back(foo_three); + x = x.push_back(foo_four); + + assert(x[y - 3].a == 1); + assert(x[y - 3].b == [2, 3, 20]); + assert(x[y - 2].a == 4); + assert(x[y - 2].b == [5, 6, 21]); + assert(x[y - 1].a == 7); + assert(x[y - 1].b == [8, 9, 22]); + assert(x[y].a == 10); + assert(x[y].b == [11, 12, 23]); + assert(x[y].bar.inner == [109, 110, 111]); + + if y != 2 { + x[y - 2].a = 50; + } else { + x[y - 2].a = 100; + } + assert(x[y - 2].a == 50); + + if y == 2 { + x[y - 1].b = [50, 51, 52]; + } else { + x[y - 1].b = [100, 101, 102]; + } + assert(x[2].b == [100, 101, 102]); + + assert(x[y - 3].bar.inner == [100, 101, 102]); + assert(x[y - 2].bar.inner == [103, 104, 105]); + assert(x[y - 1].bar.inner == [106, 107, 108]); + assert(x[y].bar.inner == [109, 110, 111]); +} diff --git a/test_programs/execution_success/nested_arrays_from_brillig/Nargo.toml b/test_programs/execution_success/nested_arrays_from_brillig/Nargo.toml new file mode 100644 index 00000000000..02d2e6e6a4e --- /dev/null +++ b/test_programs/execution_success/nested_arrays_from_brillig/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "nested_arrays_from_brillig" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/nested_arrays_from_brillig/Prover.toml b/test_programs/execution_success/nested_arrays_from_brillig/Prover.toml new file mode 100644 index 00000000000..1a59cd124a7 --- /dev/null +++ b/test_programs/execution_success/nested_arrays_from_brillig/Prover.toml @@ -0,0 +1 @@ +values = [1,2,3,4,5,6] \ No newline at end of file diff --git a/test_programs/execution_success/nested_arrays_from_brillig/src/main.nr b/test_programs/execution_success/nested_arrays_from_brillig/src/main.nr new file mode 100644 index 00000000000..f724d0cdedd --- /dev/null +++ b/test_programs/execution_success/nested_arrays_from_brillig/src/main.nr @@ -0,0 +1,27 @@ +struct Header { + params: [Field; 3], +} + +struct MyNote { + plain: Field, + array: [Field; 2], + header: Header, +} + +fn access_nested(notes: [MyNote; 2]) -> Field { + notes[0].array[1] + notes[1].array[0] + notes[0].plain + notes[1].header.params[0] +} + +unconstrained fn create_inside_brillig(values: [Field; 6]) -> [MyNote; 2] { + let header = Header { params: [values[0], values[1], values[2]] }; + let note0 = MyNote { array: [values[0], values[1]], plain: values[2], header }; + let note1 = MyNote { array: [values[3], values[4]], plain: values[5], header }; + [note0, note1] +} + +fn main(values: [Field; 6]) { + /// Safety: testing context + let notes = unsafe { create_inside_brillig(values) }; + assert(access_nested(notes) == (2 + 4 + 3 + 1)); +} + diff --git a/test_programs/execution_success/nested_dyn_array_regression_5782/Nargo.toml b/test_programs/execution_success/nested_dyn_array_regression_5782/Nargo.toml new file mode 100644 index 00000000000..b5cdd19e186 --- /dev/null +++ b/test_programs/execution_success/nested_dyn_array_regression_5782/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "nested_dyn_array_regression_5782" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/nested_dyn_array_regression_5782/Prover.toml b/test_programs/execution_success/nested_dyn_array_regression_5782/Prover.toml new file mode 100644 index 00000000000..de2960def06 --- /dev/null +++ b/test_programs/execution_success/nested_dyn_array_regression_5782/Prover.toml @@ -0,0 +1,2 @@ +array = [5, 10] +i = 1 diff --git a/test_programs/execution_success/nested_dyn_array_regression_5782/src/main.nr b/test_programs/execution_success/nested_dyn_array_regression_5782/src/main.nr new file mode 100644 index 00000000000..b6a1238a9de --- /dev/null +++ b/test_programs/execution_success/nested_dyn_array_regression_5782/src/main.nr @@ -0,0 +1,13 @@ +fn main(mut array: [Field; 2], i: u32) { + assert_eq(array[i - 1], 5); + assert_eq(array[i], 10); + + array[i] = 2; + + let array2 = [array, array]; + + assert_eq(array2[0][0], 5); + assert_eq(array2[0][i], 2); + assert_eq(array2[i][0], 5); + assert_eq(array2[i][i], 2); +} 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..82a868f3ffb --- /dev/null +++ b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr @@ -0,0 +1,33 @@ +use std::hash::poseidon2::Poseidon2; + +global NUM_HASHES: u32 = 2; +global HASH_LENGTH: u32 = 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/overlapping_dep_and_mod/Nargo.toml b/test_programs/execution_success/overlapping_dep_and_mod/Nargo.toml new file mode 100644 index 00000000000..b2c3e5f94be --- /dev/null +++ b/test_programs/execution_success/overlapping_dep_and_mod/Nargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "bin", + "foo", +] +default-member = "bin" diff --git a/test_programs/execution_success/overlapping_dep_and_mod/bin/Nargo.toml b/test_programs/execution_success/overlapping_dep_and_mod/bin/Nargo.toml new file mode 100644 index 00000000000..57e704462db --- /dev/null +++ b/test_programs/execution_success/overlapping_dep_and_mod/bin/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "overlapping_dep_and_mod" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] +foo = { path = "../foo" } diff --git a/test_programs/execution_success/overlapping_dep_and_mod/bin/Prover.toml b/test_programs/execution_success/overlapping_dep_and_mod/bin/Prover.toml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/execution_success/overlapping_dep_and_mod/bin/src/main.nr b/test_programs/execution_success/overlapping_dep_and_mod/bin/src/main.nr new file mode 100644 index 00000000000..16c940f12fc --- /dev/null +++ b/test_programs/execution_success/overlapping_dep_and_mod/bin/src/main.nr @@ -0,0 +1,14 @@ +// bin/main.nr + +fn main() -> pub Field { + assert(foo::bar() + dep::foo::bar() == 11); + assert(foo::bar() == 5); + assert(dep::foo::bar() == 6); + foo::bar() + dep::foo::bar() +} + +mod foo { + pub(crate) fn bar() -> Field { + 5 + } +} diff --git a/test_programs/execution_success/overlapping_dep_and_mod/foo/Nargo.toml b/test_programs/execution_success/overlapping_dep_and_mod/foo/Nargo.toml new file mode 100644 index 00000000000..857d4e722a8 --- /dev/null +++ b/test_programs/execution_success/overlapping_dep_and_mod/foo/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "foo" +type = "lib" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] diff --git a/test_programs/execution_success/overlapping_dep_and_mod/foo/src/lib.nr b/test_programs/execution_success/overlapping_dep_and_mod/foo/src/lib.nr new file mode 100644 index 00000000000..09283defed7 --- /dev/null +++ b/test_programs/execution_success/overlapping_dep_and_mod/foo/src/lib.nr @@ -0,0 +1,5 @@ +// foo/lib.nr + +pub fn bar() -> Field { + 6 +} diff --git a/test_programs/execution_success/pedersen_check/Nargo.toml b/test_programs/execution_success/pedersen_check/Nargo.toml new file mode 100644 index 00000000000..65fd3b5cf59 --- /dev/null +++ b/test_programs/execution_success/pedersen_check/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "pedersen_check" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/pedersen_check/Prover.toml b/test_programs/execution_success/pedersen_check/Prover.toml new file mode 100644 index 00000000000..db1ebdf6c51 --- /dev/null +++ b/test_programs/execution_success/pedersen_check/Prover.toml @@ -0,0 +1,7 @@ +x = "0" +y = "1" +salt = "42" + +out_x = "0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402" +out_y = "0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126" +out_hash = "0x0d98561fb02ca04d00801dfdc118b2a24cea0351963587712a28d368041370e1" diff --git a/test_programs/execution_success/pedersen_check/src/main.nr b/test_programs/execution_success/pedersen_check/src/main.nr new file mode 100644 index 00000000000..c71b2b570da --- /dev/null +++ b/test_programs/execution_success/pedersen_check/src/main.nr @@ -0,0 +1,20 @@ +fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { + let res = std::hash::pedersen_commitment([x, y]); + assert(res.x == out_x); + assert(res.y == out_y); + + let res_hash = std::hash::pedersen_hash_with_separator([x, y], 0); + assert_eq(res_hash, out_hash); + + assert(res_hash != res.x); + + let raw_data = [x, y]; + let mut state = 0; + for i in 0..2 { + state = state * 8 + raw_data[i]; + } + state += salt; + let hash = std::hash::pedersen_commitment([state]); + assert(std::hash::pedersen_commitment([43]).x == hash.x); +} + diff --git a/test_programs/execution_success/pedersen_commitment/Nargo.toml b/test_programs/execution_success/pedersen_commitment/Nargo.toml new file mode 100644 index 00000000000..e257ce252d8 --- /dev/null +++ b/test_programs/execution_success/pedersen_commitment/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "pedersen_commitment" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/pedersen_commitment/Prover.toml b/test_programs/execution_success/pedersen_commitment/Prover.toml new file mode 100644 index 00000000000..0279f7d2096 --- /dev/null +++ b/test_programs/execution_success/pedersen_commitment/Prover.toml @@ -0,0 +1,7 @@ +x = "0" +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 new file mode 100644 index 00000000000..c2225edcdf1 --- /dev/null +++ b/test_programs/execution_success/pedersen_commitment/src/main.nr @@ -0,0 +1,8 @@ +// docs:start:pedersen-commitment +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); +} +// docs:end:pedersen-commitment + diff --git a/test_programs/execution_success/pedersen_hash/Nargo.toml b/test_programs/execution_success/pedersen_hash/Nargo.toml new file mode 100644 index 00000000000..6248a96b3c9 --- /dev/null +++ b/test_programs/execution_success/pedersen_hash/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "pedersen_hash" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/pedersen_hash/Prover.toml b/test_programs/execution_success/pedersen_hash/Prover.toml new file mode 100644 index 00000000000..931b121fa6a --- /dev/null +++ b/test_programs/execution_success/pedersen_hash/Prover.toml @@ -0,0 +1,4 @@ +x = "0" +y = "1" + +expected_hash = "0x0d98561fb02ca04d00801dfdc118b2a24cea0351963587712a28d368041370e1" diff --git a/test_programs/execution_success/pedersen_hash/src/main.nr b/test_programs/execution_success/pedersen_hash/src/main.nr new file mode 100644 index 00000000000..de981d44bca --- /dev/null +++ b/test_programs/execution_success/pedersen_hash/src/main.nr @@ -0,0 +1,7 @@ +// docs:start:pedersen-hash +fn main(x: Field, y: Field, expected_hash: Field) { + let hash = std::hash::pedersen_hash([x, y]); + assert_eq(hash, expected_hash); +} +// docs:end:pedersen-hash + diff --git a/test_programs/execution_success/poseidon2/Nargo.toml b/test_programs/execution_success/poseidon2/Nargo.toml new file mode 100644 index 00000000000..ad812b40398 --- /dev/null +++ b/test_programs/execution_success/poseidon2/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "poseidon2" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/poseidon2/Prover.toml b/test_programs/execution_success/poseidon2/Prover.toml new file mode 100644 index 00000000000..b795ec36904 --- /dev/null +++ b/test_programs/execution_success/poseidon2/Prover.toml @@ -0,0 +1,5 @@ +inputs = ["4218458030232820015255714794613421442512497197372123294583664908262453897094", + "4218458030232820015255714794613421442512497197372123294583664908262453897094", + "4218458030232820015255714794613421442512497197372123294583664908262453897094", + "4218458030232820015255714794613421442512497197372123294583664908262453897094"] +expected_hash = "0x2f43a0f83b51a6f5fc839dea0ecec74947637802a579fa9841930a25a0bcec11" diff --git a/test_programs/execution_success/poseidon2/src/main.nr b/test_programs/execution_success/poseidon2/src/main.nr new file mode 100644 index 00000000000..3186617bfc8 --- /dev/null +++ b/test_programs/execution_success/poseidon2/src/main.nr @@ -0,0 +1,8 @@ +// docs:start:poseidon2 +use std::hash::poseidon2; + +fn main(inputs: [Field; 4], expected_hash: Field) { + let hash = poseidon2::Poseidon2::hash(inputs, inputs.len()); + assert_eq(hash, expected_hash); +} +// docs:end:poseidon2 diff --git a/test_programs/execution_success/poseidon_bn254_hash/Nargo.toml b/test_programs/execution_success/poseidon_bn254_hash/Nargo.toml new file mode 100644 index 00000000000..a8e2b3d5a2c --- /dev/null +++ b/test_programs/execution_success/poseidon_bn254_hash/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "poseidon_bn254_hash" +description = "Poseidon 254-bit permutation test on 3 elements with alpha = 5" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/poseidon_bn254_hash/Prover.toml b/test_programs/execution_success/poseidon_bn254_hash/Prover.toml new file mode 100644 index 00000000000..8eecf9a3db2 --- /dev/null +++ b/test_programs/execution_success/poseidon_bn254_hash/Prover.toml @@ -0,0 +1,4 @@ +x1 = [1,2] +y1 = "0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a" +x2 = [1,2,3,4] +y2 = "0x299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465" diff --git a/test_programs/execution_success/poseidon_bn254_hash/src/main.nr b/test_programs/execution_success/poseidon_bn254_hash/src/main.nr new file mode 100644 index 00000000000..5ea02d53e96 --- /dev/null +++ b/test_programs/execution_success/poseidon_bn254_hash/src/main.nr @@ -0,0 +1,11 @@ +// docs:start:poseidon +use std::hash::poseidon; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); +} +// docs:end:poseidon diff --git a/test_programs/execution_success/poseidon_bn254_hash_width_3/Nargo.toml b/test_programs/execution_success/poseidon_bn254_hash_width_3/Nargo.toml new file mode 100644 index 00000000000..7047f0aeef2 --- /dev/null +++ b/test_programs/execution_success/poseidon_bn254_hash_width_3/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "poseidon_bn254_hash_width_3" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" +# Test usage of `expression_width` field +expression_width = "3" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/poseidon_bn254_hash_width_3/Prover.toml b/test_programs/execution_success/poseidon_bn254_hash_width_3/Prover.toml new file mode 100644 index 00000000000..8eecf9a3db2 --- /dev/null +++ b/test_programs/execution_success/poseidon_bn254_hash_width_3/Prover.toml @@ -0,0 +1,4 @@ +x1 = [1,2] +y1 = "0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a" +x2 = [1,2,3,4] +y2 = "0x299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465" diff --git a/test_programs/execution_success/poseidon_bn254_hash_width_3/src/main.nr b/test_programs/execution_success/poseidon_bn254_hash_width_3/src/main.nr new file mode 100644 index 00000000000..bb441a1ace3 --- /dev/null +++ b/test_programs/execution_success/poseidon_bn254_hash_width_3/src/main.nr @@ -0,0 +1,9 @@ +use std::hash::poseidon; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); +} diff --git a/test_programs/execution_success/poseidonsponge_x5_254/Nargo.toml b/test_programs/execution_success/poseidonsponge_x5_254/Nargo.toml new file mode 100644 index 00000000000..de4b1a44668 --- /dev/null +++ b/test_programs/execution_success/poseidonsponge_x5_254/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "poseidonsponge_x5_254" +description = "Variable-length Poseidon-128 sponge test on 7 elements with alpha = 5" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/poseidonsponge_x5_254/Prover.toml b/test_programs/execution_success/poseidonsponge_x5_254/Prover.toml new file mode 100644 index 00000000000..f8a6be57b24 --- /dev/null +++ b/test_programs/execution_success/poseidonsponge_x5_254/Prover.toml @@ -0,0 +1 @@ +x = [1,2,3,4,5,6,7] diff --git a/test_programs/execution_success/poseidonsponge_x5_254/src/main.nr b/test_programs/execution_success/poseidonsponge_x5_254/src/main.nr new file mode 100644 index 00000000000..137f3e5d2a6 --- /dev/null +++ b/test_programs/execution_success/poseidonsponge_x5_254/src/main.nr @@ -0,0 +1,8 @@ +use std::hash::poseidon; + +fn main(x: [Field; 7]) { + // Test optimized sponge + let result = poseidon::bn254::sponge(x); + + assert(result == 0x080ae1669d62f0197190573d4a325bfb8d8fc201ce3127cbac0c47a7ac81ac48); +} diff --git a/test_programs/execution_success/pred_eq/Nargo.toml b/test_programs/execution_success/pred_eq/Nargo.toml new file mode 100644 index 00000000000..b5b4a9fdf61 --- /dev/null +++ b/test_programs/execution_success/pred_eq/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "pred_eq" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/pred_eq/Prover.toml b/test_programs/execution_success/pred_eq/Prover.toml new file mode 100644 index 00000000000..465ef562de4 --- /dev/null +++ b/test_programs/execution_success/pred_eq/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "1" diff --git a/test_programs/execution_success/pred_eq/src/main.nr b/test_programs/execution_success/pred_eq/src/main.nr new file mode 100644 index 00000000000..d1e79a3e408 --- /dev/null +++ b/test_programs/execution_success/pred_eq/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: Field, y: Field) { + let p = x == y; + assert(p == true); +} diff --git a/test_programs/execution_success/prelude/Nargo.toml b/test_programs/execution_success/prelude/Nargo.toml new file mode 100644 index 00000000000..35f223bce02 --- /dev/null +++ b/test_programs/execution_success/prelude/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "prelude" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/prelude/src/main.nr b/test_programs/execution_success/prelude/src/main.nr new file mode 100644 index 00000000000..4fe6080222e --- /dev/null +++ b/test_programs/execution_success/prelude/src/main.nr @@ -0,0 +1,31 @@ +fn main() { + let _xs: Vec = Vec::new(); + let _option: Option = Option::none(); + + print("42\n"); + println("42"); +} + +mod a { + // We don't want to give an error due to re-importing elements that are already in the prelude. + use std::collections::vec::Vec; + use std::option::Option; + + fn main() { + let _xs = Vec::new(); + let _option = Option::none(); + + print("42\n"); + println("42"); + } +} + +mod b { + fn main() { + let _xs = Vec::new(); + let _option = Option::none(); + + print("42\n"); + println("42"); + } +} diff --git a/test_programs/execution_success/ram_blowup_regression/Nargo.toml b/test_programs/execution_success/ram_blowup_regression/Nargo.toml new file mode 100644 index 00000000000..0ccbf63aa8d --- /dev/null +++ b/test_programs/execution_success/ram_blowup_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ram_blowup_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.35.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/ram_blowup_regression/Prover.toml b/test_programs/execution_success/ram_blowup_regression/Prover.toml new file mode 100644 index 00000000000..35842ce2431 --- /dev/null +++ b/test_programs/execution_success/ram_blowup_regression/Prover.toml @@ -0,0 +1 @@ +tx_effects_hash_input = [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] \ No newline at end of file diff --git a/test_programs/execution_success/ram_blowup_regression/src/main.nr b/test_programs/execution_success/ram_blowup_regression/src/main.nr new file mode 100644 index 00000000000..6deb54dd21d --- /dev/null +++ b/test_programs/execution_success/ram_blowup_regression/src/main.nr @@ -0,0 +1,41 @@ +global TX_EFFECTS_HASH_INPUT_FIELDS: u32 = 256; + +// Convert a 32 byte array to a field element by truncating the final byte +pub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field { + // Convert it to a field element + let mut v = 1; + let mut high = 0 as Field; + let mut low = 0 as Field; + + for i in 0..15 { + // covers bytes 16..30 (31 is truncated and ignored) + low = low + (bytes32[15 + 15 - i] as Field) * v; + v = v * 256; + // covers bytes 0..14 + high = high + (bytes32[14 - i] as Field) * v; + } + // covers byte 15 + low = low + (bytes32[15] as Field) * v; + + low + high * v +} + +pub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field { + let sha256_hashed = std::hash::sha256(bytes_to_hash); + let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed); + + hash_in_a_field +} + +fn main(tx_effects_hash_input: [Field; TX_EFFECTS_HASH_INPUT_FIELDS]) -> pub Field { + let mut hash_input_flattened = [0; TX_EFFECTS_HASH_INPUT_FIELDS * 32]; + for offset in 0..TX_EFFECTS_HASH_INPUT_FIELDS { + let input_as_bytes: [u8; 32] = tx_effects_hash_input[offset].to_be_bytes(); + for byte_index in 0..32 { + hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index]; + } + } + + let sha_digest = sha256_to_field(hash_input_flattened); + sha_digest +} diff --git a/test_programs/execution_success/reference_counts/Nargo.toml b/test_programs/execution_success/reference_counts/Nargo.toml new file mode 100644 index 00000000000..ae787e0ccb9 --- /dev/null +++ b/test_programs/execution_success/reference_counts/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "reference_counts" +type = "bin" +authors = [""] +compiler_version = ">=0.35.0" + +[dependencies] diff --git a/test_programs/execution_success/reference_counts/Prover.toml b/test_programs/execution_success/reference_counts/Prover.toml new file mode 100644 index 00000000000..c01dd9462d8 --- /dev/null +++ b/test_programs/execution_success/reference_counts/Prover.toml @@ -0,0 +1,2 @@ +x = 5 +b = true diff --git a/test_programs/execution_success/reference_counts/src/main.nr b/test_programs/execution_success/reference_counts/src/main.nr new file mode 100644 index 00000000000..8de4d0f2508 --- /dev/null +++ b/test_programs/execution_success/reference_counts/src/main.nr @@ -0,0 +1,78 @@ +use std::mem::array_refcount; + +fn main() { + let mut array = [0, 1, 2]; + assert_refcount(array, 1); + + borrow(array, array_refcount(array)); + borrow_mut(&mut array, array_refcount(array)); + copy_mut(array, array_refcount(array)); + + borrow_mut_two(&mut array, &mut array, array_refcount(array)); + + let mut u32_array = [0, 1, 2]; + let rc1 = array_refcount(array); + let rc2 = array_refcount(u32_array); + borrow_mut_two_separate(&mut array, &mut u32_array, rc1, rc2); +} + +fn borrow(array: [Field; 3], rc_before_call: u32) { + assert_refcount(array, rc_before_call); + println(array[0]); +} + +fn borrow_mut(array: &mut [Field; 3], rc_before_call: u32) { + // Optimization: inc_rc isn't needed since there is only one array (`array`) + // of the same type that `array` can be modified through + assert_refcount(*array, rc_before_call + 0); + array[0] = 3; + println(array[0]); +} + +fn copy_mut(mut array: [Field; 3], rc_before_call: u32) { + assert_refcount(array, rc_before_call + 1); + array[0] = 4; + println(array[0]); +} + +/// Borrow the same array mutably through both parameters, inc_rc is necessary here, although +/// only one is needed to bring the rc from 1 to 2. +fn borrow_mut_two(array1: &mut [Field; 3], array2: &mut [Field; 3], rc_before_call: u32) { + assert_refcount(*array1, rc_before_call + 1); + assert_refcount(*array2, rc_before_call + 1); + array1[0] = 5; + array2[0] = 6; + println(array1[0]); // array1 & 2 alias, so this should also print 6 + println(array2[0]); +} + +/// Borrow a different array: we should be able to reason that these types cannot be mutably +/// aliased since they're different types so we don't need any inc_rc instructions. +fn borrow_mut_two_separate( + array1: &mut [Field; 3], + array2: &mut [u32; 3], + rc_before_call1: u32, + rc_before_call2: u32, +) { + assert_refcount(*array1, rc_before_call1 + 0); + assert_refcount(*array2, rc_before_call2 + 0); + array1[0] = 7; + array2[0] = 8; + println(array1[0]); + println(array2[0]); +} + +fn assert_refcount(array: [T; 3], expected: u32) { + let count = array_refcount(array); + + // All refcounts are zero when running this as a constrained program + if std::runtime::is_unconstrained() { + if count != expected { + // Brillig doesn't print the actual & expected arguments on assertion failure + println(f"actual = {count}, expected = {expected}"); + } + assert_eq(count, expected); + } else { + assert_eq(count, 0); + } +} diff --git a/test_programs/execution_success/reference_only_used_as_alias/Nargo.toml b/test_programs/execution_success/reference_only_used_as_alias/Nargo.toml new file mode 100644 index 00000000000..d7531756822 --- /dev/null +++ b/test_programs/execution_success/reference_only_used_as_alias/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "reference_only_used_as_alias" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/reference_only_used_as_alias/Prover.toml b/test_programs/execution_success/reference_only_used_as_alias/Prover.toml new file mode 100644 index 00000000000..ef34b9eba70 --- /dev/null +++ b/test_programs/execution_success/reference_only_used_as_alias/Prover.toml @@ -0,0 +1,3 @@ +input = [0, 1, 2, 3] +context_input = 4 +randomness = 5 diff --git a/test_programs/execution_success/reference_only_used_as_alias/src/main.nr b/test_programs/execution_success/reference_only_used_as_alias/src/main.nr new file mode 100644 index 00000000000..3bbf1cf9ccb --- /dev/null +++ b/test_programs/execution_success/reference_only_used_as_alias/src/main.nr @@ -0,0 +1,93 @@ +struct ExampleEvent0 { + value0: Field, + value1: Field, +} + +trait EventInterface { + fn emit(self, _emit: fn[Env](Self) -> ()); +} + +impl EventInterface for ExampleEvent0 { + fn emit(self: ExampleEvent0, _emit: fn[Env](Self) -> ()) { + _emit(self); + } +} + +struct Context { + a: u32, + b: [u32; 3], + log_hashes: BoundedVec, +} + +struct LogHash { + value: Field, + counter: u32, + length: Field, + randomness: Field, +} + +impl Context { + fn emit_raw_log(&mut self, randomness: Field, _log: [u8; M], log_hash: Field) { + let log_hash = LogHash { value: log_hash, counter: 0, length: 0, randomness }; + self.log_hashes.push(log_hash); + } +} + +fn compute(_event: Event) -> ([u8; 5], Field) +where + Event: EventInterface, +{ + ([0 as u8; 5], 0) +} + +fn emit_with_keys( + context: &mut Context, + randomness: Field, + event: Event, + inner_compute: fn(Event) -> ([u8; OB], Field), +) +where + Event: EventInterface, +{ + let (log, log_hash) = inner_compute(event); + context.emit_raw_log(randomness, log, log_hash); +} + +fn encode_event_with_randomness( + context: &mut Context, + randomness: Field, +) -> fn[(&mut Context, Field)](Event) -> () +where + Event: EventInterface, +{ + |e: Event| { + /// Safety: testing context + unsafe { + func(context.a); + } + emit_with_keys(context, randomness, e, compute); + } +} + +unconstrained fn func(input: u32) { + let mut var = input; + let ref = &mut &mut var; + + for _ in 0..1 { + **ref = 2; + } + + assert(var == 2); + assert(**ref == 2); +} + +// This test aims to allocate a reference which is aliased and only accessed through its alias +// across multiple blocks. We want to guarantee that this allocation is not removed. +fn main(input: [Field; 4], randomness: Field, context_input: u32) { + let b = [context_input, context_input, context_input]; + let mut context = Context { a: context_input, b, log_hashes: BoundedVec::new() }; + + let event0 = ExampleEvent0 { value0: input[0], value1: input[1] }; + event0.emit(encode_event_with_randomness(&mut context, randomness)); +} + diff --git a/test_programs/execution_success/references/Nargo.toml b/test_programs/execution_success/references/Nargo.toml new file mode 100644 index 00000000000..c4be4d4218d --- /dev/null +++ b/test_programs/execution_success/references/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "references" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/references/Prover.toml b/test_programs/execution_success/references/Prover.toml new file mode 100644 index 00000000000..151faa5a9b1 --- /dev/null +++ b/test_programs/execution_success/references/Prover.toml @@ -0,0 +1 @@ +x = "2" \ No newline at end of file diff --git a/test_programs/execution_success/references/src/main.nr b/test_programs/execution_success/references/src/main.nr new file mode 100644 index 00000000000..65d70dc4a5f --- /dev/null +++ b/test_programs/execution_success/references/src/main.nr @@ -0,0 +1,244 @@ +fn main(mut x: Field) { + add1(&mut x); + assert(x == 3); + let mut s = S { y: x }; + s.add2(); + assert(s.y == 5); + // Regression for #1946: Method resolution error when calling &mut methods with a variable of type &mut T + let s_ref = &mut s; + s_ref.add2(); + assert(s.y == 7); + // Test that normal mutable variables are still copied + let mut a = 0; + mutate_copy(a); + assert(a == 0); + // Test something 3 allocations deep + let mut nested_allocations = Nested { y: &mut &mut 0 }; + add1(*nested_allocations.y); + assert(**nested_allocations.y == 1); + // Test nested struct allocations with a mutable reference to an array. + let mut c = C { foo: 0, bar: &mut C2 { array: &mut [1, 2] } }; + *c.bar.array = [3, 4]; + assert(*c.bar.array == [3, 4]); + regression_1887(); + regression_2054(); + regression_2030(); + regression_2255(); + regression_6443(); + assert(x == 3); + regression_2218_if_inner_if(x, 10); + regression_2218_if_inner_else(20, x); + regression_2218_else(x, 3); + regression_2218_loop(x, 10); + regression_2560(s_ref); +} + +fn add1(x: &mut Field) { + *x += 1; +} + +struct S { + y: Field, +} + +struct Nested { + y: &mut &mut Field, +} + +struct C { + foo: Field, + bar: &mut C2, +} + +struct C2 { + array: &mut [Field; 2], +} + +impl S { + fn add2(&mut self) { + self.y += 2; + } + + fn get_y(self) -> Field { + self.y + } +} + +fn mutate_copy(mut a: Field) { + a = 7; +} +// Previously the `foo.bar` in `foo.bar.mutate()` would insert an automatic dereference +// of `foo` which caused the method to wrongly be mutating a copy of bar rather than the original. +fn regression_1887() { + let foo = &mut Foo { bar: Bar { x: 0 } }; + foo.bar.mutate(); + assert(foo.bar.x == 32); +} + +struct Foo { + bar: Bar, +} +struct Bar { + x: Field, +} + +impl Bar { + fn mutate(&mut self) { + self.x = 32; + } +} +// Ensure that mutating a variable does not also mutate its copy +fn regression_2054() { + let mut x = 2; + let z = x; + + x += 1; + assert(z == 2); +} +// The compiler was still trying to convert an LValue from an array of structs to struct of arrays indexing, +// even though this conversion was mostly removed elsewhere. +fn regression_2030() { + let ref = &mut 0; + let mut array = [ref, ref]; + let _ = *array[0]; + *array[0] = 1; +} + +// The `mut x: &mut ...` caught a bug handling lvalues where a double-dereference would occur internally +// in one step rather than being tracked by two separate steps. This lead to assigning the 1 value to the +// incorrect outer `mut` reference rather than the correct `&mut` reference. +fn regression_2255() { + let x = &mut 0; + regression_2255_helper(x); + assert(*x == 1); +} + +fn regression_2255_helper(mut x: &mut Field) { + *x = 1; +} + +// Similar to `regression_2255` but without the double-dereferencing. +// The test checks that `mem2reg` does not eliminate storing to a reference passed as a parameter. +fn regression_6443() { + let x = &mut 0; + regression_6443_helper(x); + assert(*x == 1); +} + +fn regression_6443_helper(x: &mut Field) { + *x = 1; +} + +fn regression_2218(x: Field, y: Field) -> Field { + let q = &mut &mut 0; + let q1 = *q; + let q2 = *q; + + if x != y { + *q1 = 1; + // Make sure that we correct load reference aliases through multiple blocks + if x != 20 { + *q1 = 10; + *q2 = 2; // now we'd expect q1 == q2 == 2 + assert(*q1 == 2); + } else { + *q2 = 15; + assert(*q1 == 15); + } + } else { + *q2 = 20; + assert(*q1 == 20); + } + // Have to assign value to return it + let value = *q1; + value +} + +fn regression_2218_if_inner_if(x: Field, y: Field) { + let value = regression_2218(x, y); + assert(value == 2); +} + +fn regression_2218_if_inner_else(x: Field, y: Field) { + let value = regression_2218(x, y); + assert(value == 15); +} + +fn regression_2218_else(x: Field, y: Field) { + let value = regression_2218(x, y); + assert(value == 20); +} + +fn regression_2218_loop(x: Field, y: Field) { + let q = &mut &mut 0; + let q1 = *q; + let q2 = *q; + + for _ in 0..1 { + if x != y { + *q1 = 10; + *q2 = 2; // now we'd expect q1 == q2 == 2 + assert(*q1 == 2); + } else { + *q2 = 20; + assert(*q1 == 20); + } + } + assert(*q1 == 2); + + for _ in 0..1 { + for _ in 0..5 { + if x != y { + *q1 = 1; + // Make sure that we correct load reference aliases through multiple blocks + if x != 20 { + *q1 = 10; + *q2 = 2; // now we'd expect q1 == q2 == 2 + assert(*q1 == 2); + } + } else { + *q2 = 20; + assert(*q1 == 20); + } + } + if x != y { + *q1 = 1; + for _ in 0..5 { + // Make sure that we correct load reference aliases through multiple blocks + if x != 20 { + *q1 = 10; + *q2 = 2; // now we'd expect q1 == q2 == 2 + assert(*q1 == 2); + } + } + } else { + *q2 = 20; + assert(*q1 == 20); + } + } + assert(*q1 == 2); + + if x != y { + for _ in 0..5 { + if x != y { + *q1 = 1; + // Make sure that we correct load reference aliases through multiple blocks + if x != 20 { + *q1 = 10; + *q2 = 2; // now we'd expect q1 == q2 == 2 + assert(*q1 == 2); + } + } + } + } else { + *q2 = 20; + assert(*q1 == 20); + } + assert(*q1 == 2); +} +// This is more a feature test than a proper regression. +// Before, we never automatically dereferenced objects in method calls to their value types. +// Now, we insert as many `*` as necessary to get to `S`. +fn regression_2560(s_ref: &mut S) { + assert(s_ref.get_y() == 7); +} diff --git a/test_programs/execution_success/regression/Nargo.toml b/test_programs/execution_success/regression/Nargo.toml new file mode 100644 index 00000000000..0f6961c41d3 --- /dev/null +++ b/test_programs/execution_success/regression/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression/Prover.toml b/test_programs/execution_success/regression/Prover.toml new file mode 100644 index 00000000000..c81cbf10fbb --- /dev/null +++ b/test_programs/execution_success/regression/Prover.toml @@ -0,0 +1,4 @@ +x = [0x3f, 0x1c, 0xb8, 0x99, 0xab] +z = 3 +u = "169" +v = "-13" \ No newline at end of file diff --git a/test_programs/execution_success/regression/src/main.nr b/test_programs/execution_success/regression/src/main.nr new file mode 100644 index 00000000000..809fdbe4b28 --- /dev/null +++ b/test_programs/execution_success/regression/src/main.nr @@ -0,0 +1,141 @@ +global NIBBLE_LENGTH: u32 = 16; + +struct U4 { + inner: u8, +} + +impl U4 { + fn zero() -> U4 { + U4 { inner: 0 } + } + + fn from_u8(x: u8) -> U4 { + U4 { inner: x % 16 } + } +} + +impl Eq for U4 { + fn eq(self, other: Self) -> bool { + self.inner == other.inner + } +} + +fn compact_decode(input: [u8; N], length: Field) -> ([U4; NIBBLE_LENGTH], Field) { + assert(2 * input.len() <= NIBBLE_LENGTH); + assert(length as u32 <= input.len()); + + let mut nibble = [U4::zero(); NIBBLE_LENGTH]; + + let first_nibble = U4::from_u8(input[0] >> 4); + let parity = first_nibble.inner as u1; + + if parity == 1 { + nibble[0] = U4::from_u8(input[0] & 0x0f); + for i in 1..input.len() { + 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); + } + } + } else { + for i in 0..2 { + 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); + } + } + } + + let out = (nibble, 2 * length + (parity as Field) - 2); + + out +} + +fn enc(value: [u8; N], value_length: Field) -> ([u8; 32], Field) { + assert(value.len() as u8 >= value_length as u8); + let mut out_value = [0; 32]; + if value_length == 0 { + let out = (out_value, value_length); + out + } else if value_length as u8 < 31 { + out_value[0] = 0x80 + value_length as u8; + + for i in 1..value.len() { + out_value[i] = value[i - 1]; + } + + let out = (out_value, value_length + 1); + + out + } else { + let out = (out_value, 32); + out + } +} + +fn bitshift_literal_0() -> u64 { + let mut bits: u64 = 0; + bits |= 1 << 0; + + bits +} +fn bitshift_literal_4() -> u64 { + let mut bits: u64 = 0; + bits |= 1 << 4; + + bits +} +fn bitshift_variable(idx: u8) -> u64 { + let mut bits: u64 = 0; + bits |= 1 << idx; + + bits +} + +fn main(x: [u8; 5], z: Field, u: i16, v: i16) { + //Issue 1144 + let (nib, len) = compact_decode(x, z); + assert(len == 5); + assert( + [nib[0], nib[1], nib[2], nib[3], nib[4]] + == [U4::from_u8(15), U4::from_u8(1), U4::from_u8(12), U4::from_u8(11), U4::from_u8(8)], + ); + // Issue 1169 + let val1 = [ + 0xb8, 0x8f, 0x61, 0xe6, 0xfb, 0xda, 0x83, 0xfb, 0xff, 0xfa, 0xbe, 0x36, 0x41, 0x12, 0x13, + 0x74, 0x80, 0x39, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + ]; + let val1_length = 20; + + let enc_val1 = enc(val1, val1_length); + + assert( + enc_val1.0 + == [ + 0x94, 0xb8, 0x8f, 0x61, 0xe6, 0xfb, 0xda, 0x83, 0xfb, 0xff, 0xfa, 0xbe, 0x36, 0x41, + 0x12, 0x13, 0x74, 0x80, 0x39, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + ); + assert(enc_val1.1 == 21); + // Issue 2399 + let result_0 = bitshift_literal_0(); + assert(result_0 == 1); + let result_4 = bitshift_literal_4(); + assert(result_4 == 16); + let result_0 = bitshift_variable(0); + assert(result_0 == 1); + let result_4 = bitshift_variable(4); + assert(result_4 == 16); + + // Issue 6609 + assert(u % -13 == 0); + assert(u % v == 0); + assert(u % -11 == 4); + assert(-u % -11 == -4); + assert(u % -11 == u % (v + 2)); + assert(-u % -11 == -u % (v + 2)); +} diff --git a/test_programs/execution_success/regression_2660/Nargo.toml b/test_programs/execution_success/regression_2660/Nargo.toml new file mode 100644 index 00000000000..1ea0058684b --- /dev/null +++ b/test_programs/execution_success/regression_2660/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_2660" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/regression_2660/Prover.toml b/test_programs/execution_success/regression_2660/Prover.toml new file mode 100644 index 00000000000..4dd6b405159 --- /dev/null +++ b/test_programs/execution_success/regression_2660/Prover.toml @@ -0,0 +1 @@ +x = "1" diff --git a/test_programs/execution_success/regression_2660/src/main.nr b/test_programs/execution_success/regression_2660/src/main.nr new file mode 100644 index 00000000000..92aa15abb43 --- /dev/null +++ b/test_programs/execution_success/regression_2660/src/main.nr @@ -0,0 +1,6 @@ +global foo: i32 = -1; + +fn main(x: i32) { + let y = x + foo; + assert(y == 0); +} 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..90eb652db7a --- /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() { + std::println(1.foo()); + std::println(1.bar()); +} diff --git a/test_programs/execution_success/regression_3394/Nargo.toml b/test_programs/execution_success/regression_3394/Nargo.toml new file mode 100644 index 00000000000..4949962b16a --- /dev/null +++ b/test_programs/execution_success/regression_3394/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_3394" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_3394/Prover.toml b/test_programs/execution_success/regression_3394/Prover.toml new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/test_programs/execution_success/regression_3394/Prover.toml @@ -0,0 +1 @@ + diff --git a/test_programs/execution_success/regression_3394/src/main.nr b/test_programs/execution_success/regression_3394/src/main.nr new file mode 100644 index 00000000000..393e5c91bc2 --- /dev/null +++ b/test_programs/execution_success/regression_3394/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + let x: i8 = -128; + std::println(x); +} diff --git a/test_programs/execution_success/regression_3607/Nargo.toml b/test_programs/execution_success/regression_3607/Nargo.toml new file mode 100644 index 00000000000..8757f88b90e --- /dev/null +++ b/test_programs/execution_success/regression_3607/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_3607" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_3607/Prover.toml b/test_programs/execution_success/regression_3607/Prover.toml new file mode 100644 index 00000000000..4dd6b405159 --- /dev/null +++ b/test_programs/execution_success/regression_3607/Prover.toml @@ -0,0 +1 @@ +x = "1" diff --git a/test_programs/execution_success/regression_3607/src/main.nr b/test_programs/execution_success/regression_3607/src/main.nr new file mode 100644 index 00000000000..a2a5ed19d91 --- /dev/null +++ b/test_programs/execution_success/regression_3607/src/main.nr @@ -0,0 +1,8 @@ +fn main(mut x: u32) { + if x == 0 { + x = (x + 1) / x; + } else { + x = (x + 1) / x; + } + assert(x != 0); +} diff --git a/test_programs/execution_success/regression_3889/Nargo.toml b/test_programs/execution_success/regression_3889/Nargo.toml new file mode 100644 index 00000000000..d212d24473f --- /dev/null +++ b/test_programs/execution_success/regression_3889/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_3889" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_3889/Prover.toml b/test_programs/execution_success/regression_3889/Prover.toml new file mode 100644 index 00000000000..a81ab67fe3e --- /dev/null +++ b/test_programs/execution_success/regression_3889/Prover.toml @@ -0,0 +1,10 @@ +[works] +a = "5" + +[fails] +a = "6" + + +[also_fails] +a = "7" + diff --git a/test_programs/execution_success/regression_3889/src/main.nr b/test_programs/execution_success/regression_3889/src/main.nr new file mode 100644 index 00000000000..dfd9e8c2c85 --- /dev/null +++ b/test_programs/execution_success/regression_3889/src/main.nr @@ -0,0 +1,22 @@ +mod Foo { + struct NewType { + a: Field, + } +} + +mod Bar { + use crate::Foo::NewType; + use crate::Foo::NewType as BarStruct; +} + +mod Baz { + struct Works { + a: Field, + } + use crate::Bar::BarStruct; + use crate::Bar::NewType; +} + +fn main(works: Baz::Works, fails: Baz::BarStruct, also_fails: Bar::NewType) -> pub Field { + works.a + fails.a + also_fails.a +} diff --git a/test_programs/execution_success/regression_4088/Nargo.toml b/test_programs/execution_success/regression_4088/Nargo.toml new file mode 100644 index 00000000000..a5e7832b734 --- /dev/null +++ b/test_programs/execution_success/regression_4088/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "regression_4088" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/regression_4088/Prover.toml b/test_programs/execution_success/regression_4088/Prover.toml new file mode 100644 index 00000000000..839e31e7e40 --- /dev/null +++ b/test_programs/execution_success/regression_4088/Prover.toml @@ -0,0 +1,2 @@ +[note] +value = 0 diff --git a/test_programs/execution_success/regression_4088/src/main.nr b/test_programs/execution_success/regression_4088/src/main.nr new file mode 100644 index 00000000000..25097b14ae8 --- /dev/null +++ b/test_programs/execution_success/regression_4088/src/main.nr @@ -0,0 +1,30 @@ +trait Serialize { + fn serialize(self) -> [Field; N]; +} + +struct ValueNote { + value: Field, +} + +impl Serialize<1> for ValueNote { + fn serialize(self) -> [Field; 1] { + [self.value] + } +} + +fn check(serialized_note: [Field; N]) { + assert(serialized_note[0] == 0); +} + +fn oopsie(note: Note) +where + Note: Serialize, +{ + let serialized_note = Note::serialize(note); + + check(serialized_note) +} + +fn main(mut note: ValueNote) { + oopsie(note); +} diff --git a/test_programs/execution_success/regression_4124/Nargo.toml b/test_programs/execution_success/regression_4124/Nargo.toml new file mode 100644 index 00000000000..9b97d1ce087 --- /dev/null +++ b/test_programs/execution_success/regression_4124/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_4124" +type = "bin" +authors = [""] +compiler_version = ">=0.22.0" + +[dependencies] diff --git a/test_programs/execution_success/regression_4124/Prover.toml b/test_programs/execution_success/regression_4124/Prover.toml new file mode 100644 index 00000000000..533d1af92b9 --- /dev/null +++ b/test_programs/execution_success/regression_4124/Prover.toml @@ -0,0 +1 @@ +value = 0 diff --git a/test_programs/execution_success/regression_4124/src/main.nr b/test_programs/execution_success/regression_4124/src/main.nr new file mode 100644 index 00000000000..c2407ea91b9 --- /dev/null +++ b/test_programs/execution_success/regression_4124/src/main.nr @@ -0,0 +1,42 @@ +use std::option::Option; + +trait MyDeserialize { + fn deserialize(fields: [Field; N]) -> Self; +} + +impl MyDeserialize<1> for Field { + fn deserialize(fields: [Field; 1]) -> Self { + fields[0] + } +} + +pub fn storage_read() -> [Field; N] { + std::mem::zeroed() +} + +struct PublicMutable { + storage_slot: Field, +} + +impl PublicMutable { + pub fn new(storage_slot: Field) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + PublicMutable { storage_slot } + } + + pub fn read(_self: Self) -> T + where + T: MyDeserialize, + { + // storage_read returns slice here + let fields: [Field; T_SERIALIZED_LEN] = storage_read(); + T::deserialize(fields) + } +} + +fn main(value: Field) { + let ps: PublicMutable = PublicMutable::new(27); + + // error here + assert(ps.read() == value); +} diff --git a/test_programs/execution_success/regression_4202/Nargo.toml b/test_programs/execution_success/regression_4202/Nargo.toml new file mode 100644 index 00000000000..acfba12dd4f --- /dev/null +++ b/test_programs/execution_success/regression_4202/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_4202" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/regression_4202/Prover.toml b/test_programs/execution_success/regression_4202/Prover.toml new file mode 100644 index 00000000000..e9319802dfd --- /dev/null +++ b/test_programs/execution_success/regression_4202/Prover.toml @@ -0,0 +1 @@ +input = [1, 2, 3, 4] diff --git a/test_programs/execution_success/regression_4202/src/main.nr b/test_programs/execution_success/regression_4202/src/main.nr new file mode 100644 index 00000000000..faa14f03912 --- /dev/null +++ b/test_programs/execution_success/regression_4202/src/main.nr @@ -0,0 +1,14 @@ +fn main(input: [u32; 4]) { + let mut slice1: [u32] = &[1, 2, 3, 4]; + if slice1[0] == 3 { + slice1[1] = 4; + } + + if slice1[1] == 5 { + slice1[3] = 6; + } + + for i in 0..4 { + assert(slice1[i] == input[i]); + } +} diff --git a/test_programs/execution_success/regression_4449/Nargo.toml b/test_programs/execution_success/regression_4449/Nargo.toml new file mode 100644 index 00000000000..925420a03a8 --- /dev/null +++ b/test_programs/execution_success/regression_4449/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_4449" +type = "bin" +authors = [""] + +[dependencies] 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..3fda39bd874 --- /dev/null +++ b/test_programs/execution_success/regression_4449/src/main.nr @@ -0,0 +1,12 @@ +// Regression test for issue #4449 +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/regression_4709/Nargo.toml b/test_programs/execution_success/regression_4709/Nargo.toml new file mode 100644 index 00000000000..2e0ce3fb5af --- /dev/null +++ b/test_programs/execution_success/regression_4709/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_4709" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_4709/Prover.toml b/test_programs/execution_success/regression_4709/Prover.toml new file mode 100644 index 00000000000..dcfab705327 --- /dev/null +++ b/test_programs/execution_success/regression_4709/Prover.toml @@ -0,0 +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..9d730542641 --- /dev/null +++ b/test_programs/execution_success/regression_4709/src/main.nr @@ -0,0 +1,3854 @@ +// 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..545694368fd --- /dev/null +++ b/test_programs/execution_success/regression_5045/src/main.nr @@ -0,0 +1,20 @@ +use std::embedded_curve_ops::EmbeddedCurvePoint; +use 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 = std::embedded_curve_ops::multi_scalar_mul( + [a, bad], + [EmbeddedCurveScalar { lo: 1, hi: 0 }, EmbeddedCurveScalar { lo: 1, hi: 0 }], + ); + assert(e.x != d.x); + } +} diff --git a/test_programs/execution_success/regression_5252/Nargo.toml b/test_programs/execution_success/regression_5252/Nargo.toml new file mode 100644 index 00000000000..855507dfaf3 --- /dev/null +++ b/test_programs/execution_success/regression_5252/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5252" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/regression_5252/Prover.toml b/test_programs/execution_success/regression_5252/Prover.toml new file mode 100644 index 00000000000..82776b4463d --- /dev/null +++ b/test_programs/execution_success/regression_5252/Prover.toml @@ -0,0 +1,6 @@ +to_hash = [[1,5,9,2,24,563,3545,5,52,4244,43,2,7373567,2,286762,7,2457,24,2456,2456], +[2234,2,26,27,24566,132452,3452456344567,657,45674657,4567467,45674,4567456,4567,23454,2345,2345345245,25252345,2435234524366,8678678,67867567], +[9887575467567,5367367243617,46244567783,64673425,67456573456,4673457,46735,745674,6574,567456,7456,84,683,683,8368,38,32,16,7,98], +#[465656,234324,4353,5245246,2567345674567,5634563456,7676474,4747,4567456746,56,4657456,4657,4567,46,7,8,98,87,76,57] +] +enable = [1,1,0] diff --git a/test_programs/execution_success/regression_5252/src/main.nr b/test_programs/execution_success/regression_5252/src/main.nr new file mode 100644 index 00000000000..5f56b7f7f35 --- /dev/null +++ b/test_programs/execution_success/regression_5252/src/main.nr @@ -0,0 +1,23 @@ +use std::hash::{poseidon, poseidon2::Poseidon2}; + +global NUM_HASHES: u32 = 3; +global HASH_LENGTH: u32 = 20; + +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] { + let mut result = [0; NUM_HASHES]; + for i in 0..NUM_HASHES { + let enable = enable[i]; + let to_hash = to_hash[i]; + if enable { + result[i] = poseidon_hash(to_hash) + poseidon::bn254::sponge(to_hash); + } + } + result +} diff --git a/test_programs/execution_success/regression_5435/Nargo.toml b/test_programs/execution_success/regression_5435/Nargo.toml new file mode 100644 index 00000000000..6affc423b7a --- /dev/null +++ b/test_programs/execution_success/regression_5435/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5435" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/test_programs/execution_success/regression_5435/Prover.toml b/test_programs/execution_success/regression_5435/Prover.toml new file mode 100644 index 00000000000..f3e2bbe32e7 --- /dev/null +++ b/test_programs/execution_success/regression_5435/Prover.toml @@ -0,0 +1,2 @@ +input = "0" +enable = false diff --git a/test_programs/execution_success/regression_5435/src/main.nr b/test_programs/execution_success/regression_5435/src/main.nr new file mode 100644 index 00000000000..a83ca055aab --- /dev/null +++ b/test_programs/execution_success/regression_5435/src/main.nr @@ -0,0 +1,23 @@ +fn main(input: Field, enable: bool) { + if enable { + let hash = no_predicate_function(input); + // `EnableSideEffects` instruction from above instruction leaks out and removes the predicate from this call, + // resulting in execution failure. + /// Safety: testing context + unsafe { fail(hash) }; + } +} + +#[no_predicates] +fn no_predicate_function(enable: Field) -> Field { + // if-statement ensures that an `EnableSideEffects` instruction is emitted. + if enable == 0 { + 1 + } else { + 0 + } +} + +unconstrained fn fail(_: Field) { + assert(false); +} diff --git a/test_programs/execution_success/regression_5615/Nargo.toml b/test_programs/execution_success/regression_5615/Nargo.toml new file mode 100644 index 00000000000..738d99391a2 --- /dev/null +++ b/test_programs/execution_success/regression_5615/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5615" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/execution_success/regression_5615/src/main.nr b/test_programs/execution_success/regression_5615/src/main.nr new file mode 100644 index 00000000000..1d8e0a045cd --- /dev/null +++ b/test_programs/execution_success/regression_5615/src/main.nr @@ -0,0 +1,12 @@ +use std::collections::umap::UHashMap; +use std::hash::BuildHasherDefault; +use std::hash::poseidon2::Poseidon2Hasher; + +unconstrained fn main() { + comptime { + let mut map: UHashMap> = + UHashMap::default(); + + map.insert(1, 2); + } +} diff --git a/test_programs/execution_success/regression_6451/Nargo.toml b/test_programs/execution_success/regression_6451/Nargo.toml new file mode 100644 index 00000000000..e109747c7f6 --- /dev/null +++ b/test_programs/execution_success/regression_6451/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "regression_6451" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/regression_6451/Prover.toml b/test_programs/execution_success/regression_6451/Prover.toml new file mode 100644 index 00000000000..74213d097ec --- /dev/null +++ b/test_programs/execution_success/regression_6451/Prover.toml @@ -0,0 +1 @@ +x = 0 \ No newline at end of file diff --git a/test_programs/execution_success/regression_6451/src/main.nr b/test_programs/execution_success/regression_6451/src/main.nr new file mode 100644 index 00000000000..edef71020e4 --- /dev/null +++ b/test_programs/execution_success/regression_6451/src/main.nr @@ -0,0 +1,24 @@ +fn main(x: Field) { + // Regression test for #6451 + let y = unsafe { empty(x) }; + let mut value = 0; + let term1 = x * x - x * y; + std::as_witness(term1); + value += term1; + let term2 = x * x - y * x; + value += term2; + value.assert_max_bit_size::<1>(); + + // Regression test for #6447 (Aztec Packages issue #9488) + /// Safety: testing context + let y = unsafe { empty(x + 1) }; + let z = y + x + 1; + let z1 = z + y; + assert(z + z1 != 3); + let w = y + 2 * x + 3; + assert(w + z1 != z); +} + +unconstrained fn empty(_: Field) -> Field { + 0 +} diff --git a/test_programs/execution_success/regression_6674_1/Nargo.toml b/test_programs/execution_success/regression_6674_1/Nargo.toml new file mode 100644 index 00000000000..ad87f9deb46 --- /dev/null +++ b/test_programs/execution_success/regression_6674_1/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_6674_1" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_6674_1/src/main.nr b/test_programs/execution_success/regression_6674_1/src/main.nr new file mode 100644 index 00000000000..70315c16b78 --- /dev/null +++ b/test_programs/execution_success/regression_6674_1/src/main.nr @@ -0,0 +1,85 @@ +use std::mem::zeroed; + +pub struct BoundedVec4 { + storage: [Field; 4], + len: u32, +} + +impl BoundedVec4 { + pub fn new() -> Self { + BoundedVec4 { storage: [0; 4], len: 0 } + } + + pub fn push(&mut self, elem: Field) { + self.storage[self.len] = elem; + self.len += 1; + } +} + +pub struct PrivateKernelCircuitPublicInputs { + pub l2_to_l1_msgs: [Field; 4], + pub public_call_requests: [Field; 4], +} + +pub struct FixtureBuilder { + pub public_call_requests: BoundedVec4, + pub counter: Field, +} + +impl FixtureBuilder { + pub fn new() -> Self { + FixtureBuilder { public_call_requests: zeroed(), counter: 0 } + } + + pub fn append_public_call_requests_inner(&mut self) { + self.public_call_requests.push(self.next_counter()); + } + + pub fn append_public_call_requests(&mut self) { + for _ in 0..4 { + // Note that here we push via a method call + self.append_public_call_requests_inner(); + } + } + + fn next_counter(&mut self) -> Field { + let counter = self.counter; + self.counter += 1; + counter + } +} + +pub struct PrivateKernelCircuitPublicInputsComposer { + pub l2_to_l1_msgs: [Field; 4], + pub public_call_requests: [Field; 4], +} + +pub unconstrained fn sort_by(array: [Field; 4]) -> [Field; 4] { + let result = array; + get_sorting_index(array); + result +} + +unconstrained fn get_sorting_index(array: [Field; 4]) { + let _ = [0; 4]; + let mut a = array; + for i in 1..4 { + for j in 0..i { + a[i] = a[j]; + } + } +} + +unconstrained fn main() { + let mut previous_kernel = FixtureBuilder::new(); + previous_kernel.append_public_call_requests(); + + let mut output_composer = PrivateKernelCircuitPublicInputsComposer { + l2_to_l1_msgs: [0; 4], + public_call_requests: previous_kernel.public_call_requests.storage, + }; + output_composer.l2_to_l1_msgs = sort_by(output_composer.l2_to_l1_msgs); + output_composer.public_call_requests = sort_by(output_composer.public_call_requests); + + assert_eq(previous_kernel.public_call_requests.storage[1], 1, "equality"); +} diff --git a/test_programs/execution_success/regression_6674_2/Nargo.toml b/test_programs/execution_success/regression_6674_2/Nargo.toml new file mode 100644 index 00000000000..666765c8172 --- /dev/null +++ b/test_programs/execution_success/regression_6674_2/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_6674_2" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_6674_2/src/main.nr b/test_programs/execution_success/regression_6674_2/src/main.nr new file mode 100644 index 00000000000..42ad4fa4031 --- /dev/null +++ b/test_programs/execution_success/regression_6674_2/src/main.nr @@ -0,0 +1,87 @@ +use std::mem::zeroed; + +pub struct BoundedVec4 { + storage: [Field; 4], + len: u32, +} + +impl BoundedVec4 { + pub fn new() -> Self { + BoundedVec4 { storage: [0; 4], len: 0 } + } + + pub fn push(&mut self, elem: Field) { + self.storage[self.len] = elem; + self.len += 1; + } +} + +pub struct PrivateKernelCircuitPublicInputs { + pub l2_to_l1_msgs: [Field; 4], + pub public_call_requests: [Field; 4], +} + +pub struct FixtureBuilder { + pub public_call_requests: BoundedVec4, + pub counter: Field, +} + +impl FixtureBuilder { + pub fn new() -> Self { + FixtureBuilder { public_call_requests: zeroed(), counter: 0 } + } + + pub fn append_public_call_requests(&mut self) { + for _ in 0..4 { + // Note that here we push directly, not through a method call + self.public_call_requests.push(self.next_counter()); + } + } + + fn next_counter(&mut self) -> Field { + let counter = self.counter; + self.counter += 1; + counter + } +} + +pub struct PrivateKernelCircuitPublicInputsComposer { + pub l2_to_l1_msgs: [Field; 4], + pub public_call_requests: [Field; 4], +} + +impl PrivateKernelCircuitPublicInputsComposer { + pub unconstrained fn sort_ordered_values(&mut self) { + self.l2_to_l1_msgs = sort_by(self.l2_to_l1_msgs); + self.public_call_requests = sort_by(self.public_call_requests); + } +} + +pub unconstrained fn sort_by(array: [Field; 4]) -> [Field; 4] { + let result = array; + get_sorting_index(array); + result +} + +unconstrained fn get_sorting_index(array: [Field; 4]) { + let _ = [0; 4]; + let mut a = array; + for i in 1..4 { + for j in 0..i { + a[i] = a[j]; + } + } +} + +unconstrained fn main() { + let mut previous_kernel = FixtureBuilder::new(); + previous_kernel.append_public_call_requests(); + + let mut output_composer = PrivateKernelCircuitPublicInputsComposer { + l2_to_l1_msgs: [0; 4], + public_call_requests: previous_kernel.public_call_requests.storage, + }; + output_composer.sort_ordered_values(); + + assert_eq(previous_kernel.public_call_requests.storage[1], 1, "equality"); +} diff --git a/test_programs/execution_success/regression_6674_3/Nargo.toml b/test_programs/execution_success/regression_6674_3/Nargo.toml new file mode 100644 index 00000000000..7b396f63693 --- /dev/null +++ b/test_programs/execution_success/regression_6674_3/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_6674_3" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_6674_3/src/main.nr b/test_programs/execution_success/regression_6674_3/src/main.nr new file mode 100644 index 00000000000..57a3df5fcac --- /dev/null +++ b/test_programs/execution_success/regression_6674_3/src/main.nr @@ -0,0 +1,191 @@ +use std::mem::zeroed; + +pub struct PrivateAccumulatedData { + pub public_call_requests: [Counted; 4], +} + +pub struct PrivateAccumulatedDataBuilder { + pub l2_to_l1_msgs: BoundedVec, + pub public_call_requests: BoundedVec, 4>, + pub private_call_stack: BoundedVec, +} + +impl PrivateAccumulatedDataBuilder { + pub fn finish(self) -> PrivateAccumulatedData { + PrivateAccumulatedData { public_call_requests: self.public_call_requests.storage() } + } +} + +pub struct Counted { + pub inner: T, + pub counter: u32, +} + +impl Counted { + pub fn new(inner: T, counter: u32) -> Self { + Self { inner, counter } + } +} + +pub struct PrivateKernelCircuitPublicInputs { + pub end: PrivateAccumulatedData, +} + +pub struct PrivateKernelData { + pub public_inputs: PrivateKernelCircuitPublicInputs, +} + +pub struct FixtureBuilder2 { + pub public_teardown_call_request: Field, + pub private_call_requests: BoundedVec, + pub public_call_requests: BoundedVec, 4>, + pub counter: u32, +} + +impl FixtureBuilder2 { + pub fn new() -> Self { + let mut builder: FixtureBuilder2 = zeroed(); + builder.counter = 1; + builder + } + + pub fn to_private_accumulated_data_builder(self) -> PrivateAccumulatedDataBuilder { + PrivateAccumulatedDataBuilder { + l2_to_l1_msgs: zeroed(), + public_call_requests: self.public_call_requests, + private_call_stack: vec_reverse(self.private_call_requests), + } + } + + pub fn to_private_accumulated_data(self) -> PrivateAccumulatedData { + self.to_private_accumulated_data_builder().finish() + } + + pub fn to_private_kernel_circuit_public_inputs(self) -> PrivateKernelCircuitPublicInputs { + PrivateKernelCircuitPublicInputs { end: self.to_private_accumulated_data() } + } + + pub fn to_private_kernel_data(self) -> PrivateKernelData { + let public_inputs = + PrivateKernelCircuitPublicInputs { end: self.to_private_accumulated_data() }; + PrivateKernelData { public_inputs } + } + + pub fn add_public_call_request(&mut self) { + self.public_call_requests.push(Counted::new(zeroed(), self.next_counter())); + } + + pub fn append_public_call_requests(&mut self, num: u32) { + for _ in 0..num { + self.add_public_call_request(); + } + } + + pub fn set_public_teardown_call_request(&mut self) { + let mut fields = [0; 5]; + for i in 0..5 { + fields[i] = i as Field; + } + + self.public_teardown_call_request = zeroed(); + } + + fn next_counter(&mut self) -> u32 { + let counter = self.counter; + self.counter += 1; + counter + } +} + +struct PrivateKernelTailToPublicInputsBuilder { + previous_kernel: FixtureBuilder2, +} + +impl PrivateKernelTailToPublicInputsBuilder { + pub unconstrained fn execute(&mut self) { + let kernel = PrivateKernelTailToPublicCircuitPrivateInputs { + previous_kernel: self.previous_kernel.to_private_kernel_data(), + }; + let mut output_composer = PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel( + kernel.previous_kernel.public_inputs, + ); + output_composer.sort_ordered_values(); + } +} + +pub struct PrivateKernelTailToPublicCircuitPrivateInputs { + previous_kernel: PrivateKernelData, +} + +pub struct PrivateKernelCircuitPublicInputsComposer { + public_inputs: PrivateKernelCircuitPublicInputsBuilder, +} + +impl PrivateKernelCircuitPublicInputsComposer { + pub unconstrained fn sort_ordered_values(&mut self) { + // Note hashes, nullifiers, and private logs are sorted in the reset circuit. + self.public_inputs.end.l2_to_l1_msgs.storage = + sort_by_counter_desc(self.public_inputs.end.l2_to_l1_msgs.storage); + self.public_inputs.end.public_call_requests.storage = + sort_by_counter_desc(self.public_inputs.end.public_call_requests.storage); + } +} + +impl PrivateKernelCircuitPublicInputsComposer { + pub fn new_from_previous_kernel( + previous_kernel_public_inputs: PrivateKernelCircuitPublicInputs, + ) -> Self { + let mut public_inputs: PrivateKernelCircuitPublicInputsBuilder = zeroed(); + let start = previous_kernel_public_inputs.end; + public_inputs.end.public_call_requests = BoundedVec { + storage: start.public_call_requests, + len: start.public_call_requests.len(), + }; + PrivateKernelCircuitPublicInputsComposer { public_inputs } + } +} + +pub struct PrivateKernelCircuitPublicInputsBuilder { + end: PrivateAccumulatedDataBuilder, +} + +fn vec_reverse(vec: BoundedVec) -> BoundedVec { + let mut reversed = BoundedVec::new(); + let len = vec.len(); + for i in 0..N { + if i < len { + reversed.push(vec.get_unchecked(len - i - 1)); + } + } + reversed +} + +pub unconstrained fn sort_by_counter_desc(array: [T; N]) -> [T; N] { + sort_by(array) +} + +pub unconstrained fn sort_by(array: [T; N]) -> [T; N] { + let mut result = array; + get_sorting_index(array); + result +} + +unconstrained fn get_sorting_index(array: [T; N]) { + let _ = [0; 4]; + let mut a = array; + for i in 1..4 { + for j in 0..i { + a[i] = a[j]; + } + } +} + +unconstrained fn main() { + let mut previous_kernel = FixtureBuilder2::new(); + let mut builder = PrivateKernelTailToPublicInputsBuilder { previous_kernel }; + builder.previous_kernel.append_public_call_requests(4); + assert_eq(builder.previous_kernel.public_call_requests.storage[3].counter, 4); + builder.previous_kernel.set_public_teardown_call_request(); + builder.execute(); + assert_eq(builder.previous_kernel.public_call_requests.storage[3].counter, 4); +} diff --git a/test_programs/execution_success/regression_6734/Nargo.toml b/test_programs/execution_success/regression_6734/Nargo.toml new file mode 100644 index 00000000000..4c757bab454 --- /dev/null +++ b/test_programs/execution_success/regression_6734/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_6734" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_6734/src/main.nr b/test_programs/execution_success/regression_6734/src/main.nr new file mode 100644 index 00000000000..87cac64aaa1 --- /dev/null +++ b/test_programs/execution_success/regression_6734/src/main.nr @@ -0,0 +1,24 @@ +// https://github.com/noir-lang/noir/issues/6734 + +pub fn sub_array_extended( + src: [Field; SRC_LEN], + offset: u32, +) -> [Field; DST_LEN] { + let available_elements_to_copy = SRC_LEN - offset; + let elements_to_copy = if DST_LEN > available_elements_to_copy { + available_elements_to_copy + } else { + DST_LEN + }; + + let mut dst: [Field; DST_LEN] = std::mem::zeroed(); + for i in 0..elements_to_copy { + dst[i] = src[i + offset]; + } + + dst +} + +unconstrained fn main() { + assert_eq(sub_array_extended([], 0), []); +} diff --git a/test_programs/execution_success/regression_6834/Nargo.toml b/test_programs/execution_success/regression_6834/Nargo.toml new file mode 100644 index 00000000000..edc3257d52d --- /dev/null +++ b/test_programs/execution_success/regression_6834/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_6834" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_6834/Prover.toml b/test_programs/execution_success/regression_6834/Prover.toml new file mode 100644 index 00000000000..9ef840487ad --- /dev/null +++ b/test_programs/execution_success/regression_6834/Prover.toml @@ -0,0 +1,2 @@ +year = 1 +min_age = 1 diff --git a/test_programs/execution_success/regression_6834/src/main.nr b/test_programs/execution_success/regression_6834/src/main.nr new file mode 100644 index 00000000000..cea8d163ab5 --- /dev/null +++ b/test_programs/execution_success/regression_6834/src/main.nr @@ -0,0 +1,9 @@ +fn main(year: u32, min_age: u8) -> pub u32 { + if min_age == 0 { + (year - 2) / 4 + } else if year > 1 { + (year - 2) / 4 + } else { + 0 + } +} diff --git a/test_programs/execution_success/regression_bignum/Nargo.toml b/test_programs/execution_success/regression_bignum/Nargo.toml new file mode 100644 index 00000000000..5cadd364e43 --- /dev/null +++ b/test_programs/execution_success/regression_bignum/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_bignum" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_bignum/src/main.nr b/test_programs/execution_success/regression_bignum/src/main.nr new file mode 100644 index 00000000000..013ab6b2023 --- /dev/null +++ b/test_programs/execution_success/regression_bignum/src/main.nr @@ -0,0 +1,51 @@ +fn main() { + let numerator = + [790096867046896348, 1063071665130103641, 602707730209562162, 996751591622961462, 28650, 0]; + unsafe { __udiv_mod(numerator) }; + + let denominator = [12, 0, 0, 0, 0, 0]; + let result = unsafe { __validate_gt_remainder(denominator) }; + assert(result[4] == 0); + assert(result[5] == 0); +} + +unconstrained fn __udiv_mod(remainder_u60: [u64; 6]) { + let bit_difference = get_msb(remainder_u60); + let accumulator_u60: [u64; 6] = shl(bit_difference); +} + +unconstrained fn __validate_gt_remainder(a_u60: [u64; 6]) -> [u64; 6] { + let mut addend_u60: [u64; 6] = [0; 6]; + let mut result_u60: [u64; 6] = [0; 6]; + + for i in 0..6 { + result_u60[i] = a_u60[i] + addend_u60[i]; + } + + result_u60 +} + +unconstrained fn get_msb(val: [u64; 6]) -> u32 { + let mut count = 0; + for i in 0..6 { + let v = val[(6 - 1) - i]; + if (v > 0) { + count = 60 * ((6 - 1) - i); + break; + } + } + count +} + +unconstrained fn shl(shift: u32) -> [u64; 6] { + let num_shifted_limbs = shift / 60; + let limb_shift = (shift % 60) as u8; + + let mut result = [0; 6]; + result[num_shifted_limbs] = (1 << limb_shift); + + for i in 1..(6 - num_shifted_limbs) { + result[i + num_shifted_limbs] = 0; + } + result +} 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..11690b5c186 --- /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_mem_op_predicate/Nargo.toml b/test_programs/execution_success/regression_mem_op_predicate/Nargo.toml new file mode 100644 index 00000000000..93a0ba6f25a --- /dev/null +++ b/test_programs/execution_success/regression_mem_op_predicate/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_mem_op_predicate" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_mem_op_predicate/Prover.toml b/test_programs/execution_success/regression_mem_op_predicate/Prover.toml new file mode 100644 index 00000000000..3621f24082c --- /dev/null +++ b/test_programs/execution_success/regression_mem_op_predicate/Prover.toml @@ -0,0 +1,2 @@ +x = [4,3,1,5,111] +idx = 12 \ No newline at end of file diff --git a/test_programs/execution_success/regression_mem_op_predicate/src/main.nr b/test_programs/execution_success/regression_mem_op_predicate/src/main.nr new file mode 100644 index 00000000000..4b5ca67f6de --- /dev/null +++ b/test_programs/execution_success/regression_mem_op_predicate/src/main.nr @@ -0,0 +1,8 @@ +fn main(mut x: [u32; 5], idx: Field) { + // We should not hit out of bounds here as we have a predicate + // that should not be hit + if idx as u32 < 3 { + x[idx] = 10; + } + assert(x[4] == 111); +} diff --git a/test_programs/execution_success/regression_method_cannot_be_found/Nargo.toml b/test_programs/execution_success/regression_method_cannot_be_found/Nargo.toml new file mode 100644 index 00000000000..aed6aa06714 --- /dev/null +++ b/test_programs/execution_success/regression_method_cannot_be_found/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_method_cannot_be_found" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_method_cannot_be_found/Prover.toml b/test_programs/execution_success/regression_method_cannot_be_found/Prover.toml new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/test_programs/execution_success/regression_method_cannot_be_found/Prover.toml @@ -0,0 +1 @@ + diff --git a/test_programs/execution_success/regression_method_cannot_be_found/src/main.nr b/test_programs/execution_success/regression_method_cannot_be_found/src/main.nr new file mode 100644 index 00000000000..c7db543f1bb --- /dev/null +++ b/test_programs/execution_success/regression_method_cannot_be_found/src/main.nr @@ -0,0 +1,22 @@ +struct Item { + id: Field, +} + +impl Item { + fn log(self) { + let id = self.id; + std::println(id); + } +} + +fn create(something: V) -> V { + something +} + +fn main() { + let a = Item { id: 1 }; + let b = create(a); + let _id = b.id; + // Regression for: cannot find this method + b.log(); +} 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..fe5f1ef1918 --- /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/regression_unsafe_no_predicates/Nargo.toml b/test_programs/execution_success/regression_unsafe_no_predicates/Nargo.toml new file mode 100644 index 00000000000..7cd42687c34 --- /dev/null +++ b/test_programs/execution_success/regression_unsafe_no_predicates/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "regression_unsafe_no_predicates" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/regression_unsafe_no_predicates/Prover.toml b/test_programs/execution_success/regression_unsafe_no_predicates/Prover.toml new file mode 100644 index 00000000000..aaa42715899 --- /dev/null +++ b/test_programs/execution_success/regression_unsafe_no_predicates/Prover.toml @@ -0,0 +1,2 @@ +x = 239 +nest = false \ No newline at end of file diff --git a/test_programs/execution_success/regression_unsafe_no_predicates/src/main.nr b/test_programs/execution_success/regression_unsafe_no_predicates/src/main.nr new file mode 100644 index 00000000000..b4dd6a57e80 --- /dev/null +++ b/test_programs/execution_success/regression_unsafe_no_predicates/src/main.nr @@ -0,0 +1,24 @@ +fn main(x: u8, nest: bool) { + if nest { + let foo = unsafe_assert([x]); + assert(foo != 0); + } +} + +#[no_predicates] +pub fn unsafe_assert(msg: [u8; N]) -> u8 { + /// Safety: testing context + let block = unsafe { get_block(msg) }; + verify_block(msg, block); + block[0] +} + +unconstrained fn get_block(msg: [u8; N]) -> [u8; 2] { + let mut block: [u8; 2] = [0; 2]; + block[0] = msg[0]; + block +} + +fn verify_block(msg: [u8; N], block: [u8; 2]) { + assert_eq(block[0], msg[0]); +} diff --git a/test_programs/execution_success/return_twice/Nargo.toml b/test_programs/execution_success/return_twice/Nargo.toml new file mode 100644 index 00000000000..defd68f37b8 --- /dev/null +++ b/test_programs/execution_success/return_twice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "return_twice" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/return_twice/Prover.toml b/test_programs/execution_success/return_twice/Prover.toml new file mode 100644 index 00000000000..b343065a7fc --- /dev/null +++ b/test_programs/execution_success/return_twice/Prover.toml @@ -0,0 +1,2 @@ +return = [100, 100] +in0 = 10 diff --git a/test_programs/execution_success/return_twice/src/main.nr b/test_programs/execution_success/return_twice/src/main.nr new file mode 100644 index 00000000000..68bd5f916ce --- /dev/null +++ b/test_programs/execution_success/return_twice/src/main.nr @@ -0,0 +1,5 @@ +pub fn main(in0: Field) -> pub (Field, Field) { + let out0 = (in0 * in0); + let out1 = (in0 * in0); + (out0, out1) +} diff --git a/test_programs/execution_success/sha256/Nargo.toml b/test_programs/execution_success/sha256/Nargo.toml new file mode 100644 index 00000000000..255d2156ef6 --- /dev/null +++ b/test_programs/execution_success/sha256/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "sha256" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/sha256/Prover.toml b/test_programs/execution_success/sha256/Prover.toml new file mode 100644 index 00000000000..b4bf4162370 --- /dev/null +++ b/test_programs/execution_success/sha256/Prover.toml @@ -0,0 +1,38 @@ + +x = 0xbd +result = [ + 0x68, + 0x32, + 0x57, + 0x20, + 0xaa, + 0xbd, + 0x7c, + 0x82, + 0xf3, + 0x0f, + 0x55, + 0x4b, + 0x31, + 0x3d, + 0x05, + 0x70, + 0xc9, + 0x5a, + 0xcc, + 0xbb, + 0x7d, + 0xc4, + 0xb5, + 0xaa, + 0xe1, + 0x12, + 0x04, + 0xc0, + 0x8f, + 0xfe, + 0x73, + 0x2b, +] +input = [0, 0] +toggle = false \ No newline at end of file diff --git a/test_programs/execution_success/sha256/src/main.nr b/test_programs/execution_success/sha256/src/main.nr new file mode 100644 index 00000000000..8e5e46b9837 --- /dev/null +++ b/test_programs/execution_success/sha256/src/main.nr @@ -0,0 +1,27 @@ +// Sha256 example +// +// Calls Sha256 from the standard library. +// +// The Compiler sees this special function and creates an ACIR gate +// +// The ACIR SHA256 gate is passed to PLONK who should +// know how to create the necessary constraints. +// +// Not yet here: For R1CS, it is more about manipulating arithmetic gates to get performance +// This can be done in ACIR! +fn main(x: Field, result: [u8; 32], input: [u8; 2], toggle: bool) { + // 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 + // docs:start:sha256_var + let digest = std::hash::sha256_var([x as u8], 1); + // docs:end:sha256_var + assert(digest == result); + + let digest = std::hash::sha256([x as u8]); + assert(digest == result); + + // variable size + let size: Field = 1 + toggle as Field; + let var_sha = std::hash::sha256_var(input, size as u64); + assert(var_sha == std::hash::sha256_var(input, 1)); +} diff --git a/test_programs/execution_success/sha256_brillig_performance_regression/Nargo.toml b/test_programs/execution_success/sha256_brillig_performance_regression/Nargo.toml new file mode 100644 index 00000000000..f7076311e1d --- /dev/null +++ b/test_programs/execution_success/sha256_brillig_performance_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "sha256_brillig_performance_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] diff --git a/test_programs/execution_success/sha256_brillig_performance_regression/Prover.toml b/test_programs/execution_success/sha256_brillig_performance_regression/Prover.toml new file mode 100644 index 00000000000..5bb7f354257 --- /dev/null +++ b/test_programs/execution_success/sha256_brillig_performance_regression/Prover.toml @@ -0,0 +1,16 @@ +input_amount = "1" +minimum_output_amount = "2" +secret_hash_for_L1_to_l2_message = "3" +uniswap_fee_tier = "4" + +[aztec_recipient] +inner = "5" + +[caller_on_L1] +inner = "6" + +[input_asset_bridge_portal_address] +inner = "7" + +[output_asset_bridge_portal_address] +inner = "8" diff --git a/test_programs/execution_success/sha256_brillig_performance_regression/src/main.nr b/test_programs/execution_success/sha256_brillig_performance_regression/src/main.nr new file mode 100644 index 00000000000..42cc6d4ff3b --- /dev/null +++ b/test_programs/execution_success/sha256_brillig_performance_regression/src/main.nr @@ -0,0 +1,104 @@ +// Performance regression extracted from an aztec protocol contract. + +unconstrained fn main( + input_asset_bridge_portal_address: EthAddress, + input_amount: Field, + uniswap_fee_tier: Field, + output_asset_bridge_portal_address: EthAddress, + minimum_output_amount: Field, + aztec_recipient: AztecAddress, + secret_hash_for_L1_to_l2_message: Field, + caller_on_L1: EthAddress, +) -> pub Field { + let mut hash_bytes = [0; 260]; // 8 fields of 32 bytes each + 4 bytes fn selector + let input_token_portal_bytes: [u8; 32] = + input_asset_bridge_portal_address.to_field().to_be_bytes(); + let in_amount_bytes: [u8; 32] = input_amount.to_be_bytes(); + let uniswap_fee_tier_bytes: [u8; 32] = uniswap_fee_tier.to_be_bytes(); + let output_token_portal_bytes: [u8; 32] = + output_asset_bridge_portal_address.to_field().to_be_bytes(); + let amount_out_min_bytes: [u8; 32] = minimum_output_amount.to_be_bytes(); + let aztec_recipient_bytes: [u8; 32] = aztec_recipient.to_field().to_be_bytes(); + let secret_hash_for_L1_to_l2_message_bytes: [u8; 32] = + secret_hash_for_L1_to_l2_message.to_be_bytes(); + let caller_on_L1_bytes: [u8; 32] = caller_on_L1.to_field().to_be_bytes(); + + // The purpose of including the following selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. + let selector = comptime { + std::hash::keccak256( + "swap_public(address,uint256,uint24,address,uint256,bytes32,bytes32,address)".as_bytes(), + 75, + ) + }; + + hash_bytes[0] = selector[0]; + hash_bytes[1] = selector[1]; + hash_bytes[2] = selector[2]; + hash_bytes[3] = selector[3]; + + for i in 0..32 { + hash_bytes[i + 4] = input_token_portal_bytes[i]; + hash_bytes[i + 36] = in_amount_bytes[i]; + hash_bytes[i + 68] = uniswap_fee_tier_bytes[i]; + hash_bytes[i + 100] = output_token_portal_bytes[i]; + hash_bytes[i + 132] = amount_out_min_bytes[i]; + hash_bytes[i + 164] = aztec_recipient_bytes[i]; + hash_bytes[i + 196] = secret_hash_for_L1_to_l2_message_bytes[i]; + hash_bytes[i + 228] = caller_on_L1_bytes[i]; + } + + let content_hash = sha256_to_field(hash_bytes); + content_hash +} + +// Convert a 32 byte array to a field element by truncating the final byte +pub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field { + // Convert it to a field element + let mut v = 1; + let mut high = 0 as Field; + let mut low = 0 as Field; + + for i in 0..15 { + // covers bytes 16..30 (31 is truncated and ignored) + low = low + (bytes32[15 + 15 - i] as Field) * v; + v = v * 256; + // covers bytes 0..14 + high = high + (bytes32[14 - i] as Field) * v; + } + // covers byte 15 + low = low + (bytes32[15] as Field) * v; + + low + high * v +} + +pub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field { + let sha256_hashed = std::hash::sha256(bytes_to_hash); + let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed); + + hash_in_a_field +} + +pub trait ToField { + fn to_field(self) -> Field; +} + +pub struct EthAddress { + inner: Field, +} + +impl ToField for EthAddress { + fn to_field(self) -> Field { + self.inner + } +} + +pub struct AztecAddress { + pub inner: Field, +} + +impl ToField for AztecAddress { + fn to_field(self) -> Field { + self.inner + } +} diff --git a/test_programs/execution_success/sha256_regression/Nargo.toml b/test_programs/execution_success/sha256_regression/Nargo.toml new file mode 100644 index 00000000000..ce98d000bcb --- /dev/null +++ b/test_programs/execution_success/sha256_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "sha256_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/sha256_regression/Prover.toml b/test_programs/execution_success/sha256_regression/Prover.toml new file mode 100644 index 00000000000..ea0a0f2e8a7 --- /dev/null +++ b/test_programs/execution_success/sha256_regression/Prover.toml @@ -0,0 +1,14 @@ +msg_just_over_block = [102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116] +msg_multiple_of_block = [102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 115, 45, 97, 115, 99, 105, 105, 13, 10, 109, 105, 109, 101, 45, 118, 101, 114, 115, 105, 111, 110, 58, 49, 46, 48, 32, 40, 77, 97, 99, 32, 79, 83, 32, 88, 32, 77, 97, 105, 108, 32, 49, 54, 46, 48, 32, 92, 40, 51, 55, 51, 49, 46, 53, 48, 48, 46, 50, 51, 49, 92, 41, 41, 13, 10, 115, 117, 98, 106, 101, 99, 116, 58, 72, 101, 108, 108, 111, 13, 10, 109, 101, 115, 115, 97, 103, 101, 45, 105, 100, 58, 60, 56, 70, 56, 49, 57, 68, 51, 50, 45, 66, 54, 65, 67, 45, 52, 56, 57, 68, 45, 57, 55, 55, 70, 45, 52, 51, 56, 66, 66, 67, 52, 67, 65, 66, 50, 55, 64, 109, 101, 46, 99, 111, 109, 62, 13, 10, 100, 97, 116, 101, 58, 83, 97, 116, 44, 32, 50, 54, 32, 65, 117, 103, 32, 50, 48, 50, 51, 32, 49, 50, 58, 50, 53, 58, 50, 50, 32, 43, 48, 52, 48, 48, 13, 10, 116, 111, 58, 122, 107, 101, 119, 116, 101, 115, 116, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109, 13, 10, 100, 107, 105, 109, 45, 115, 105, 103, 110, 97, 116, 117, 114, 101, 58, 118, 61, 49, 59, 32, 97, 61, 114, 115, 97, 45, 115, 104, 97, 50, 53, 54, 59, 32, 99, 61, 114, 101, 108, 97, 120, 101, 100, 47, 114, 101, 108, 97, 120, 101, 100, 59, 32, 100, 61, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 59, 32, 115, 61, 49, 97, 49, 104, 97, 105, 59, 32, 116, 61, 49, 54, 57, 51, 48, 51, 56, 51, 51, 55, 59, 32, 98, 104, 61, 55, 120, 81, 77, 68, 117, 111, 86, 86, 85, 52, 109, 48, 87, 48, 87, 82, 86, 83, 114, 86, 88, 77, 101, 71, 83, 73, 65, 83, 115, 110, 117, 99, 75, 57, 100, 74, 115, 114, 99, 43, 118, 85, 61, 59, 32, 104, 61, 102, 114, 111, 109, 58, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 77, 105, 109, 101, 45, 86, 101, 114, 115, 105, 111, 110, 58, 83, 117, 98, 106, 101, 99] +msg_just_under_block = [102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59] +msg_big_not_block_multiple = [102, 114, 111, 109, 58, 114, 117, 110, 110, 105, 101, 114, 46, 108, 101, 97, 103, 117, 101, 115, 46, 48, 106, 64, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 13, 10, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, 112, 101, 58, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 115, 45, 97, 115, 99, 105, 105, 13, 10, 109, 105, 109, 101, 45, 118, 101, 114, 115, 105, 111, 110, 58, 49, 46, 48, 32, 40, 77, 97, 99, 32, 79, 83, 32, 88, 32, 77, 97, 105, 108, 32, 49, 54, 46, 48, 32, 92, 40, 51, 55, 51, 49, 46, 53, 48, 48, 46, 50, 51, 49, 92, 41, 41, 13, 10, 115, 117, 98, 106, 101, 99, 116, 58, 72, 101, 108, 108, 111, 13, 10, 109, 101, 115, 115, 97, 103, 101, 45, 105, 100, 58, 60, 56, 70, 56, 49, 57, 68, 51, 50, 45, 66, 54, 65, 67, 45, 52, 56, 57, 68, 45, 57, 55, 55, 70, 45, 52, 51, 56, 66, 66, 67, 52, 67, 65, 66, 50, 55, 64, 109, 101, 46, 99, 111, 109, 62, 13, 10, 100, 97, 116, 101, 58, 83, 97, 116, 44, 32, 50, 54, 32, 65, 117, 103, 32, 50, 48, 50, 51, 32, 49, 50, 58, 50, 53, 58, 50, 50, 32, 43, 48, 52, 48, 48, 13, 10, 116, 111, 58, 122, 107, 101, 119, 116, 101, 115, 116, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109, 13, 10, 100, 107, 105, 109, 45, 115, 105, 103, 110, 97, 116, 117, 114, 101, 58, 118, 61, 49, 59, 32, 97, 61, 114, 115, 97, 45, 115, 104, 97, 50, 53, 54, 59, 32, 99, 61, 114, 101, 108, 97, 120, 101, 100, 47, 114, 101, 108, 97, 120, 101, 100, 59, 32, 100, 61, 105, 99, 108, 111, 117, 100, 46, 99, 111, 109, 59, 32, 115, 61, 49, 97, 49, 104, 97, 105, 59, 32, 116, 61, 49, 54, 57, 51, 48, 51, 56, 51, 51, 55, 59, 32, 98, 104, 61, 55, 120, 81, 77, 68, 117, 111, 86, 86, 85, 52, 109, 48, 87, 48, 87, 82, 86, 83, 114, 86, 88, 77, 101, 71, 83, 73, 65, 83, 115, 110, 117, 99, 75, 57, 100, 74, 115, 114, 99, 43, 118, 85, 61, 59, 32, 104, 61, 102, 114, 111, 109, 58, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 77, 105, 109, 101, 45, 86, 101, 114, 115, 105, 111, 110, 58, 83, 117, 98, 106, 101, 99, 116, 58, 77, 101, 115, 115, 97, 103, 101, 45, 73, 100, 58, 68, 97, 116, 101, 58, 116, 111, 59, 32, 98, 61] +msg_big_with_padding = [48, 130, 1, 37, 2, 1, 0, 48, 11, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 48, 130, 1, 17, 48, 37, 2, 1, 1, 4, 32, 176, 223, 31, 133, 108, 84, 158, 102, 70, 11, 165, 175, 196, 12, 201, 130, 25, 131, 46, 125, 156, 194, 28, 23, 55, 133, 157, 164, 135, 136, 220, 78, 48, 37, 2, 1, 2, 4, 32, 190, 82, 180, 235, 222, 33, 79, 50, 152, 136, 142, 35, 116, 224, 6, 242, 156, 141, 128, 248, 10, 61, 98, 86, 248, 45, 207, 210, 90, 232, 175, 38, 48, 37, 2, 1, 3, 4, 32, 0, 194, 104, 108, 237, 246, 97, 230, 116, 198, 69, 110, 26, 87, 17, 89, 110, 199, 108, 250, 36, 21, 39, 87, 110, 102, 250, 213, 174, 131, 171, 174, 48, 37, 2, 1, 11, 4, 32, 136, 155, 87, 144, 111, 15, 152, 127, 85, 25, 154, 81, 20, 58, 51, 75, 193, 116, 234, 0, 60, 30, 29, 30, 183, 141, 72, 247, 255, 203, 100, 124, 48, 37, 2, 1, 12, 4, 32, 41, 234, 106, 78, 31, 11, 114, 137, 237, 17, 92, 71, 134, 47, 62, 78, 189, 233, 201, 214, 53, 4, 47, 189, 201, 133, 6, 121, 34, 131, 64, 142, 48, 37, 2, 1, 13, 4, 32, 91, 222, 210, 193, 62, 222, 104, 82, 36, 41, 138, 253, 70, 15, 148, 208, 156, 45, 105, 171, 241, 195, 185, 43, 217, 162, 146, 201, 222, 89, 238, 38, 48, 37, 2, 1, 14, 4, 32, 76, 123, 216, 13, 51, 227, 72, 245, 59, 193, 238, 166, 103, 49, 23, 164, 171, 188, 194, 197, 156, 187, 249, 28, 198, 95, 69, 15, 182, 56, 54, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +msg_big_no_padding = [48, 130, 1, 37, 2, 1, 0, 48, 11, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 48, 130, 1, 17, 48, 37, 2, 1, 1, 4, 32, 176, 223, 31, 133, 108, 84, 158, 102, 70, 11, 165, 175, 196, 12, 201, 130, 25, 131, 46, 125, 156, 194, 28, 23, 55, 133, 157, 164, 135, 136, 220, 78, 48, 37, 2, 1, 2, 4, 32, 190, 82, 180, 235, 222, 33, 79, 50, 152, 136, 142, 35, 116, 224, 6, 242, 156, 141, 128, 248, 10, 61, 98, 86, 248, 45, 207, 210, 90, 232, 175, 38, 48, 37, 2, 1, 3, 4, 32, 0, 194, 104, 108, 237, 246, 97, 230, 116, 198, 69, 110, 26, 87, 17, 89, 110, 199, 108, 250, 36, 21, 39, 87, 110, 102, 250, 213, 174, 131, 171, 174, 48, 37, 2, 1, 11, 4, 32, 136, 155, 87, 144, 111, 15, 152, 127, 85, 25, 154, 81, 20, 58, 51, 75, 193, 116, 234, 0, 60, 30, 29, 30, 183, 141, 72, 247, 255, 203, 100, 124, 48, 37, 2, 1, 12, 4, 32, 41, 234, 106, 78, 31, 11, 114, 137, 237, 17, 92, 71, 134, 47, 62, 78, 189, 233, 201, 214, 53, 4, 47, 189, 201, 133, 6, 121, 34, 131, 64, 142, 48, 37, 2, 1, 13, 4, 32, 91, 222, 210, 193, 62, 222, 104, 82, 36, 41, 138, 253, 70, 15, 148, 208, 156, 45, 105, 171, 241, 195, 185, 43, 217, 162, 146, 201, 222, 89, 238, 38, 48, 37, 2, 1, 14, 4, 32, 76, 123, 216, 13, 51, 227, 72, 245, 59, 193, 238, 166, 103, 49, 23, 164, 171, 188, 194, 197, 156, 187, 249, 28, 198, 95, 69, 15, 182, 56, 54, 38] +message_size = 297 + +# Results matched against ethers library +result_just_over_block = [91, 122, 146, 93, 52, 109, 133, 148, 171, 61, 156, 70, 189, 238, 153, 7, 222, 184, 94, 24, 65, 114, 192, 244, 207, 199, 87, 232, 192, 224, 171, 207] +result_multiple_of_block = [116, 90, 151, 31, 78, 22, 138, 180, 211, 189, 69, 76, 227, 200, 155, 29, 59, 123, 154, 60, 47, 153, 203, 129, 157, 251, 48, 2, 79, 11, 65, 47] +result_just_under_block = [143, 140, 76, 173, 222, 123, 102, 68, 70, 149, 207, 43, 39, 61, 34, 79, 216, 252, 213, 165, 74, 16, 110, 74, 29, 64, 138, 167, 30, 1, 9, 119] +result_big = [112, 144, 73, 182, 208, 98, 9, 238, 54, 229, 61, 145, 222, 17, 72, 62, 148, 222, 186, 55, 192, 82, 220, 35, 66, 47, 193, 200, 22, 38, 26, 186] +result_big_with_padding = [32, 85, 108, 174, 127, 112, 178, 182, 8, 43, 134, 123, 192, 211, 131, 66, 184, 240, 212, 181, 240, 180, 106, 195, 24, 117, 54, 129, 19, 10, 250, 53] \ No newline at end of file diff --git a/test_programs/execution_success/sha256_regression/src/main.nr b/test_programs/execution_success/sha256_regression/src/main.nr new file mode 100644 index 00000000000..dbbcc07e501 --- /dev/null +++ b/test_programs/execution_success/sha256_regression/src/main.nr @@ -0,0 +1,39 @@ +// A bunch of different test cases for sha256_var in the stdlib +fn main( + msg_just_over_block: [u8; 68], + result_just_over_block: pub [u8; 32], + msg_multiple_of_block: [u8; 448], + result_multiple_of_block: pub [u8; 32], + // We want to make sure we are testing a message with a size >= 57 but < 64 + msg_just_under_block: [u8; 60], + result_just_under_block: pub [u8; 32], + msg_big_not_block_multiple: [u8; 472], + result_big: pub [u8; 32], + // This message is only 297 elements and we want to hash only a variable amount + msg_big_with_padding: [u8; 700], + // This is the same as `msg_big_with_padding` but with no padding + msg_big_no_padding: [u8; 297], + message_size: u64, + result_big_with_padding: pub [u8; 32], +) { + let hash = std::hash::sha256_var(msg_just_over_block, msg_just_over_block.len() as u64); + assert_eq(hash, result_just_over_block); + + let hash = std::hash::sha256_var(msg_multiple_of_block, msg_multiple_of_block.len() as u64); + assert_eq(hash, result_multiple_of_block); + + let hash = std::hash::sha256_var(msg_just_under_block, msg_just_under_block.len() as u64); + assert_eq(hash, result_just_under_block); + + let hash = std::hash::sha256_var( + msg_big_not_block_multiple, + msg_big_not_block_multiple.len() as u64, + ); + assert_eq(hash, result_big); + + let hash_padding = std::hash::sha256_var(msg_big_with_padding, message_size); + assert_eq(hash_padding, result_big_with_padding); + + let hash_no_padding = std::hash::sha256_var(msg_big_no_padding, message_size); + assert_eq(hash_no_padding, result_big_with_padding); +} diff --git a/test_programs/execution_success/sha256_var_padding_regression/Nargo.toml b/test_programs/execution_success/sha256_var_padding_regression/Nargo.toml new file mode 100644 index 00000000000..a80677c585d --- /dev/null +++ b/test_programs/execution_success/sha256_var_padding_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "sha256_var_padding_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.34.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/sha256_var_padding_regression/Prover.toml b/test_programs/execution_success/sha256_var_padding_regression/Prover.toml new file mode 100644 index 00000000000..7b20e870128 --- /dev/null +++ b/test_programs/execution_success/sha256_var_padding_regression/Prover.toml @@ -0,0 +1,2 @@ +preimage = [29, 81, 165, 84, 243, 114, 101, 37, 242, 146, 127, 99, 69, 145, 39, 72, 213, 39, 253, 179, 218, 37, 217, 201, 172, 93, 198, 50, 249, 70, 15, 30, 162, 112, 187, 40, 140, 9, 236, 53, 32, 44, 38, 163, 113, 254, 192, 197, 44, 89, 71, 130, 169, 242, 17, 211, 214, 72, 19, 178, 186, 168, 147, 127, 99, 101, 252, 227, 8, 147, 150, 85, 97, 158, 17, 107, 218, 244, 82, 113, 247, 91, 208, 214, 60, 244, 87, 137, 173, 201, 130, 18, 66, 56, 198, 149, 207, 189, 175, 120, 123, 224, 177, 167, 251, 159, 143, 110, 68, 183, 189, 70, 126, 32, 35, 164, 44, 30, 44, 12, 65, 18, 62, 239, 242, 2, 248, 104, 2, 178, 64, 28, 126, 36, 137, 24, 14, 116, 91, 98, 90, 159, 218, 102, 45, 11, 110, 223, 245, 184, 52, 99, 59, 245, 136, 175, 3, 72, 164, 146, 145, 116, 22, 66, 24, 49, 193, 121, 3, 60, 37, 41, 97, 3, 190, 66, 195, 225, 63, 46, 3, 118, 4, 208, 15, 1, 40, 254, 235, 151, 123, 70, 180, 170, 44, 172, 90, 4, 254, 53, 239, 116, 246, 67, 56, 129, 61, 22, 169, 213, 65, 27, 216, 116, 162, 239, 214, 207, 126, 177, 20, 100, 25, 48, 143, 84, 215, 70, 197, 53, 65, 70, 86, 172, 61, 62, 9, 212, 167, 169, 133, 41, 126, 213, 196, 33, 192, 238, 0, 63, 246, 215, 58, 128, 110, 101, 92, 3, 170, 214, 130, 149, 52, 81, 125, 118, 233, 3, 118, 193, 104, 207, 120, 115, 77, 253, 191, 122, 0, 107, 164, 207, 113, 81, 169, 36, 201, 228, 74, 134, 131, 218, 178, 35, 30, 216, 101, 2, 103, 174, 87, 95, 50, 50, 215, 157, 5, 210, 188, 54, 211, 78, 45, 199, 96, 121, 241, 241, 176, 226, 194, 134, 130, 89, 217, 210, 186, 32, 140, 39, 91, 103, 212, 26, 87, 32, 72, 144, 228, 230, 117, 99, 188, 50, 15, 69, 79, 179, 50, 12, 106, 86, 218, 101, 73, 142, 243, 29, 250, 122, 228, 233, 29, 255, 22, 121, 114, 125, 103, 41, 250, 241, 179, 126, 158, 198, 116, 209, 65, 94, 98, 228, 175, 169, 96, 3, 9, 233, 133, 214, 55, 161, 164, 103, 80, 85, 24, 186, 64, 167, 92, 131, 53, 101, 202, 47, 25, 104, 118, 155, 14, 12, 12, 25, 116, 45, 221, 249, 28, 246, 212, 200, 157, 167, 169, 56, 197, 181, 4, 245, 146, 1, 140, 234, 191, 212, 228, 125, 87, 81, 86, 119, 30, 63, 129, 143, 32, 96] +result = [205, 74, 73, 134, 202, 93, 199, 152, 171, 244, 133, 193, 132, 40, 42, 9, 248, 11, 99, 200, 135, 58, 220, 227, 45, 253, 183, 241, 69, 69, 80, 219] \ No newline at end of file diff --git a/test_programs/execution_success/sha256_var_padding_regression/src/main.nr b/test_programs/execution_success/sha256_var_padding_regression/src/main.nr new file mode 100644 index 00000000000..13f87a0efc5 --- /dev/null +++ b/test_programs/execution_success/sha256_var_padding_regression/src/main.nr @@ -0,0 +1,29 @@ +// Test to check sha256_var produces same results irrespective of number of padding bytes after message.length +// Ref: https://github.com/noir-lang/noir/issues/6163, https://gist.github.com/jp4g/d5953faae9eadb2909357474f7901e58 +fn main(preimage: [u8; 448], result: [u8; 32]) { + // Construct arrays of different lengths + let mut preimage_511 = [0; 511]; + let mut preimage_512 = [0; 512]; // Next block + let mut preimage_575 = [0; 575]; + let mut preimage_576 = [0; 576]; // Next block + for i in 0..preimage.len() { + preimage_511[i] = preimage[i]; + preimage_512[i] = preimage[i]; + preimage_575[i] = preimage[i]; + preimage_576[i] = preimage[i]; + } + let fixed_length_hash = std::hash::sha256::digest(preimage); + let var_full_length_hash = std::hash::sha256::sha256_var(preimage, preimage.len() as u64); + let var_length_hash_511 = std::hash::sha256::sha256_var(preimage_511, preimage.len() as u64); + let var_length_hash_512 = std::hash::sha256::sha256_var(preimage_512, preimage.len() as u64); + let var_length_hash_575 = std::hash::sha256::sha256_var(preimage_575, preimage.len() as u64); + let var_length_hash_576 = std::hash::sha256::sha256_var(preimage_576, preimage.len() as u64); + + // All of the above should have produced the same hash (result) + assert(fixed_length_hash == result); + assert(var_full_length_hash == result); + assert(var_length_hash_511 == result); + assert(var_length_hash_512 == result); + assert(var_length_hash_575 == result); + assert(var_length_hash_576 == result); +} diff --git a/test_programs/execution_success/sha256_var_size_regression/Nargo.toml b/test_programs/execution_success/sha256_var_size_regression/Nargo.toml new file mode 100644 index 00000000000..3e141ee5d5f --- /dev/null +++ b/test_programs/execution_success/sha256_var_size_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "sha256_var_size_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/sha256_var_size_regression/Prover.toml b/test_programs/execution_success/sha256_var_size_regression/Prover.toml new file mode 100644 index 00000000000..df632a42858 --- /dev/null +++ b/test_programs/execution_success/sha256_var_size_regression/Prover.toml @@ -0,0 +1,3 @@ +enable = [true, false] +foo = [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] +toggle = false diff --git a/test_programs/execution_success/sha256_var_size_regression/src/main.nr b/test_programs/execution_success/sha256_var_size_regression/src/main.nr new file mode 100644 index 00000000000..4278cdda8a3 --- /dev/null +++ b/test_programs/execution_success/sha256_var_size_regression/src/main.nr @@ -0,0 +1,17 @@ +global NUM_HASHES: u32 = 2; + +fn main(foo: [u8; 95], toggle: bool, enable: [bool; NUM_HASHES]) { + let mut result = [[0; 32]; NUM_HASHES]; + let mut const_result = [[0; 32]; NUM_HASHES]; + let size: Field = 93 + toggle as Field * 2; + for i in 0..NUM_HASHES { + if enable[i] { + result[i] = std::sha256::sha256_var(foo, size as u64); + const_result[i] = std::sha256::sha256_var(foo, 93); + } + } + + for i in 0..NUM_HASHES { + assert_eq(result[i], const_result[i]); + } +} diff --git a/test_programs/execution_success/sha256_var_witness_const_regression/Nargo.toml b/test_programs/execution_success/sha256_var_witness_const_regression/Nargo.toml new file mode 100644 index 00000000000..e8f3e6bbe64 --- /dev/null +++ b/test_programs/execution_success/sha256_var_witness_const_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "sha256_var_witness_const_regression" +type = "bin" +authors = [""] +compiler_version = ">=0.33.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/sha256_var_witness_const_regression/Prover.toml b/test_programs/execution_success/sha256_var_witness_const_regression/Prover.toml new file mode 100644 index 00000000000..7b91051c1a0 --- /dev/null +++ b/test_programs/execution_success/sha256_var_witness_const_regression/Prover.toml @@ -0,0 +1,2 @@ +input = [0, 0] +toggle = false \ No newline at end of file diff --git a/test_programs/execution_success/sha256_var_witness_const_regression/src/main.nr b/test_programs/execution_success/sha256_var_witness_const_regression/src/main.nr new file mode 100644 index 00000000000..97c4435d41d --- /dev/null +++ b/test_programs/execution_success/sha256_var_witness_const_regression/src/main.nr @@ -0,0 +1,9 @@ +fn main(input: [u8; 2], toggle: bool) { + let size: Field = 1 + toggle as Field; + assert(!toggle); + + let variable_sha = std::sha256::sha256_var(input, size as u64); + let constant_sha = std::sha256::sha256_var(input, 1); + + assert_eq(variable_sha, constant_sha); +} diff --git a/test_programs/execution_success/sha2_byte/Nargo.toml b/test_programs/execution_success/sha2_byte/Nargo.toml new file mode 100644 index 00000000000..efd691fce58 --- /dev/null +++ b/test_programs/execution_success/sha2_byte/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "sha2_byte" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/sha2_byte/Prover.toml b/test_programs/execution_success/sha2_byte/Prover.toml new file mode 100644 index 00000000000..2f82f14a58d --- /dev/null +++ b/test_programs/execution_success/sha2_byte/Prover.toml @@ -0,0 +1,5 @@ +# Values obtainable from https://emn178.github.io/online-tools/sha256.html and https://emn178.github.io/online-tools/sha512.html +x = 0xbd +result256 = [0x68, 0x32, 0x57, 0x20, 0xaa, 0xbd, 0x7c, 0x82, 0xf3, 0x0f, 0x55, 0x4b, 0x31, 0x3d, 0x05, 0x70, 0xc9, 0x5a, 0xcc, 0xbb, 0x7d, 0xc4, 0xb5, 0xaa, 0xe1, 0x12, 0x04, 0xc0, 0x8f, 0xfe, 0x73, 0x2b] +result512 = [0x29, 0x6e, 0x22, 0x67, 0xd7, 0x4c, 0x27, 0x8d, 0xaa, 0xaa, 0x94, 0x0d, 0x17, 0xb0, 0xcf, 0xb7, 0x4a, 0x50, 0x83, 0xf8, 0xe0, 0x69, 0x72, 0x6d, 0x8c, 0x84, 0x1c, 0xbe, 0x59, 0x6e, 0x04, 0x31, 0xcb, 0x77, 0x41, 0xa5, 0xb5, 0x0f, 0x71, 0x66, 0x6c, 0xfd, 0x54, 0xba, 0xcb, 0x7b, 0x00, 0xae, 0xa8, 0x91, 0x49, 0x9c, 0xf4, 0xef, 0x6a, 0x03, 0xc8, 0xa8, 0x3f, 0xe3, 0x7c, 0x3f, 0x7b, 0xaf] + diff --git a/test_programs/execution_success/sha2_byte/src/main.nr b/test_programs/execution_success/sha2_byte/src/main.nr new file mode 100644 index 00000000000..a1663642c69 --- /dev/null +++ b/test_programs/execution_success/sha2_byte/src/main.nr @@ -0,0 +1,8 @@ +// Test Noir implementations of SHA256 and SHA512 on a one-byte message. +fn main(x: Field, result256: [u8; 32], result512: [u8; 64]) { + let digest256 = std::hash::sha256([x as u8]); + assert(digest256 == result256); + + let digest512 = std::hash::sha512::digest([x as u8]); + assert(digest512 == result512); +} diff --git a/test_programs/execution_success/side_effects_constrain_array/Nargo.toml b/test_programs/execution_success/side_effects_constrain_array/Nargo.toml new file mode 100644 index 00000000000..fc817f0921f --- /dev/null +++ b/test_programs/execution_success/side_effects_constrain_array/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "side_effects_constrain_array" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/side_effects_constrain_array/Prover.toml b/test_programs/execution_success/side_effects_constrain_array/Prover.toml new file mode 100644 index 00000000000..7127baac5bf --- /dev/null +++ b/test_programs/execution_success/side_effects_constrain_array/Prover.toml @@ -0,0 +1 @@ +y = "3" diff --git a/test_programs/execution_success/side_effects_constrain_array/src/main.nr b/test_programs/execution_success/side_effects_constrain_array/src/main.nr new file mode 100644 index 00000000000..c4a62603bc3 --- /dev/null +++ b/test_programs/execution_success/side_effects_constrain_array/src/main.nr @@ -0,0 +1,17 @@ +struct Bar { + inner: [Field; 3], +} + +fn main(y: pub u32) { + let bar = Bar { inner: [100, 101, 102] }; + + // The assert inside the if should be hit + if y < 10 { + assert(bar.inner == [100, 101, 102]); + } + + // The assert inside the if should not be hit + if y > 10 { + assert(bar.inner == [0, 1, 2]); + } +} diff --git a/test_programs/execution_success/signed_arithmetic/Nargo.toml b/test_programs/execution_success/signed_arithmetic/Nargo.toml new file mode 100644 index 00000000000..47676a806e8 --- /dev/null +++ b/test_programs/execution_success/signed_arithmetic/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "signed_arithmetic" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/signed_arithmetic/Prover.toml b/test_programs/execution_success/signed_arithmetic/Prover.toml new file mode 100644 index 00000000000..e0e584b7380 --- /dev/null +++ b/test_programs/execution_success/signed_arithmetic/Prover.toml @@ -0,0 +1,3 @@ +x = "5" +y = "8" +z = "-15" diff --git a/test_programs/execution_success/signed_arithmetic/src/main.nr b/test_programs/execution_success/signed_arithmetic/src/main.nr new file mode 100644 index 00000000000..9b72b688bc5 --- /dev/null +++ b/test_programs/execution_success/signed_arithmetic/src/main.nr @@ -0,0 +1,32 @@ +fn main(mut x: i32, mut y: i32, z: i32) { + let mut s1: i8 = 5; + let mut s2: i8 = 8; + assert(s1 + s2 == 13); + assert(x + y == 13); + + s2 = -8; + y = -y; + assert(s1 + s2 == -3); + assert(x + y == -3); + + s1 = -15; + assert(s1 - s2 == -7); + assert(z - y == -7); + + s1 = -5; + s2 = 8; + x = -x; + y = -y; + assert(s1 - s2 == -13); + assert(x - y == -13); + + s2 = -8; + y = -y; + assert(s1 * s2 == 40); + assert(x * y == 40); + + s1 = 1; + s2 = -8; + assert(s1 * s2 == -8); + assert(x / x * y == -8); +} diff --git a/test_programs/execution_success/signed_cmp/Nargo.toml b/test_programs/execution_success/signed_cmp/Nargo.toml new file mode 100644 index 00000000000..642a0924678 --- /dev/null +++ b/test_programs/execution_success/signed_cmp/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "signed_cmp" +type = "bin" +authors = [""] + +[dependencies] 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/signed_comparison/Nargo.toml b/test_programs/execution_success/signed_comparison/Nargo.toml new file mode 100644 index 00000000000..c8de162877b --- /dev/null +++ b/test_programs/execution_success/signed_comparison/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "signed_comparison" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/signed_comparison/Prover.toml b/test_programs/execution_success/signed_comparison/Prover.toml new file mode 100644 index 00000000000..e0e584b7380 --- /dev/null +++ b/test_programs/execution_success/signed_comparison/Prover.toml @@ -0,0 +1,3 @@ +x = "5" +y = "8" +z = "-15" diff --git a/test_programs/execution_success/signed_comparison/src/main.nr b/test_programs/execution_success/signed_comparison/src/main.nr new file mode 100644 index 00000000000..0fe72112f5a --- /dev/null +++ b/test_programs/execution_success/signed_comparison/src/main.nr @@ -0,0 +1,11 @@ +fn main(mut x: i8, mut y: i8, z: i8) { + let mut s1: i8 = 5; + let mut s2: i8 = 8; + assert(-1 as i8 < 0); + assert(x < y); + assert(-x < y); + assert(-y < -x); + assert((z > x) == false); + assert(x <= s1); + assert(z < x - y - s2); +} diff --git a/test_programs/execution_success/signed_div/Nargo.toml b/test_programs/execution_success/signed_div/Nargo.toml new file mode 100644 index 00000000000..5ce137d8c0c --- /dev/null +++ b/test_programs/execution_success/signed_div/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "signed_div" +type = "bin" +authors = [""] + +[dependencies] 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/execution_success/signed_division/Nargo.toml b/test_programs/execution_success/signed_division/Nargo.toml new file mode 100644 index 00000000000..0d631a00b05 --- /dev/null +++ b/test_programs/execution_success/signed_division/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "signed_division" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/signed_division/Prover.toml b/test_programs/execution_success/signed_division/Prover.toml new file mode 100644 index 00000000000..ee6f0ef229a --- /dev/null +++ b/test_programs/execution_success/signed_division/Prover.toml @@ -0,0 +1,3 @@ +x = "7" +y = "3" +z = "2" \ No newline at end of file diff --git a/test_programs/execution_success/signed_division/src/main.nr b/test_programs/execution_success/signed_division/src/main.nr new file mode 100644 index 00000000000..64ba4a5354c --- /dev/null +++ b/test_programs/execution_success/signed_division/src/main.nr @@ -0,0 +1,20 @@ +// Testing signed integer division: +// 7/3 = 2 +// -7/3 = -2 +// -7/-3 = 2 +// 7/-3 = -2 +fn main(mut x: i32, mut y: i32, mut z: i32) { + // 7/3 = 2 + assert(x / y == z); + // -7/3 = -2 + let minus_x = std::wrapping_sub(0, x); + let minus_z = std::wrapping_sub(0, z); + let minus_y = std::wrapping_sub(0, y); + assert(x + minus_x == 0); + assert(z + minus_z == 0); + assert(minus_x / y == minus_z); + // -7/-3 = 2 + assert(minus_x / minus_y == z); + // 7/-3 = -2 + assert(x / minus_y == minus_z); +} diff --git a/test_programs/execution_success/simple_2d_array/Nargo.toml b/test_programs/execution_success/simple_2d_array/Nargo.toml new file mode 100644 index 00000000000..b6d22d82631 --- /dev/null +++ b/test_programs/execution_success/simple_2d_array/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "simple_2d_array" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/simple_2d_array/Prover.toml b/test_programs/execution_success/simple_2d_array/Prover.toml new file mode 100644 index 00000000000..a4616f907bb --- /dev/null +++ b/test_programs/execution_success/simple_2d_array/Prover.toml @@ -0,0 +1,3 @@ +x = "1" +y = "2" +array_input = [[1, 2], [3, 3]] diff --git a/test_programs/execution_success/simple_2d_array/src/main.nr b/test_programs/execution_success/simple_2d_array/src/main.nr new file mode 100644 index 00000000000..2ecdd4bc15f --- /dev/null +++ b/test_programs/execution_success/simple_2d_array/src/main.nr @@ -0,0 +1,8 @@ +// Test accessing a multidimensional array +fn main(x: Field, y: Field, array_input: [[Field; 2]; 2]) { + assert(array_input[0][0] == x); + assert(array_input[0][1] == y); + + let arr: [[Field; 2]; 1] = [[3, 3]]; + assert_eq(arr[0], array_input[1]); +} diff --git a/test_programs/execution_success/simple_add_and_ret_arr/Nargo.toml b/test_programs/execution_success/simple_add_and_ret_arr/Nargo.toml new file mode 100644 index 00000000000..6c5b0e4ca9a --- /dev/null +++ b/test_programs/execution_success/simple_add_and_ret_arr/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "simple_add_and_ret_arr" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/simple_add_and_ret_arr/Prover.toml b/test_programs/execution_success/simple_add_and_ret_arr/Prover.toml new file mode 100644 index 00000000000..3d2b4b14efe --- /dev/null +++ b/test_programs/execution_success/simple_add_and_ret_arr/Prover.toml @@ -0,0 +1 @@ +x = 1 \ No newline at end of file diff --git a/test_programs/execution_success/simple_add_and_ret_arr/src/main.nr b/test_programs/execution_success/simple_add_and_ret_arr/src/main.nr new file mode 100644 index 00000000000..891ea9c4982 --- /dev/null +++ b/test_programs/execution_success/simple_add_and_ret_arr/src/main.nr @@ -0,0 +1,8 @@ +// A simple program to test that SSA array values elements +// aren't disconnected from their instruction results, and +// that dead instruction elemination looks inside of arrays +// when deciding whether of not an instruction should be +// retained. +fn main(x: Field) -> pub [Field; 1] { + [x + 1] +} diff --git a/test_programs/execution_success/simple_array_param/Nargo.toml b/test_programs/execution_success/simple_array_param/Nargo.toml new file mode 100644 index 00000000000..4f1811cc669 --- /dev/null +++ b/test_programs/execution_success/simple_array_param/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "simple_array_param" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/simple_array_param/Prover.toml b/test_programs/execution_success/simple_array_param/Prover.toml new file mode 100644 index 00000000000..66f0b9ccc1c --- /dev/null +++ b/test_programs/execution_success/simple_array_param/Prover.toml @@ -0,0 +1 @@ +xs = [0, 1] diff --git a/test_programs/execution_success/simple_array_param/src/main.nr b/test_programs/execution_success/simple_array_param/src/main.nr new file mode 100644 index 00000000000..6dd7c34dab5 --- /dev/null +++ b/test_programs/execution_success/simple_array_param/src/main.nr @@ -0,0 +1,6 @@ +// This program tests: +// - the allocation of virtual arrays for array params to main +// - load instructions for such arrays +fn main(xs: [Field; 2]) -> pub Field { + xs[1] +} diff --git a/test_programs/execution_success/simple_bitwise/Nargo.toml b/test_programs/execution_success/simple_bitwise/Nargo.toml new file mode 100644 index 00000000000..be425f22e5c --- /dev/null +++ b/test_programs/execution_success/simple_bitwise/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "simple_bitwise" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/simple_bitwise/Prover.toml b/test_programs/execution_success/simple_bitwise/Prover.toml new file mode 100644 index 00000000000..aa3715f9b3d --- /dev/null +++ b/test_programs/execution_success/simple_bitwise/Prover.toml @@ -0,0 +1,4 @@ +a = 1 +b = 0 +c = "10" +d = "11" diff --git a/test_programs/execution_success/simple_bitwise/src/main.nr b/test_programs/execution_success/simple_bitwise/src/main.nr new file mode 100644 index 00000000000..9ab738ae04d --- /dev/null +++ b/test_programs/execution_success/simple_bitwise/src/main.nr @@ -0,0 +1,9 @@ +fn main(a: bool, b: bool, c: u8, d: u8) -> pub u8 { + let i = a & b; + let j = a ^ b; + let k = a | b; + let x = c & d; + let y = c ^ d; + let z = c | d; + (i as u8) + (j as u8) + (k as u8) + x + y + z +} diff --git a/test_programs/execution_success/simple_comparison/Nargo.toml b/test_programs/execution_success/simple_comparison/Nargo.toml new file mode 100644 index 00000000000..06685628444 --- /dev/null +++ b/test_programs/execution_success/simple_comparison/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "simple_comparison" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/simple_comparison/Prover.toml b/test_programs/execution_success/simple_comparison/Prover.toml new file mode 100644 index 00000000000..ed94d313315 --- /dev/null +++ b/test_programs/execution_success/simple_comparison/Prover.toml @@ -0,0 +1,2 @@ +x = "3" +y = "4" diff --git a/test_programs/execution_success/simple_comparison/src/main.nr b/test_programs/execution_success/simple_comparison/src/main.nr new file mode 100644 index 00000000000..45c4e4a0321 --- /dev/null +++ b/test_programs/execution_success/simple_comparison/src/main.nr @@ -0,0 +1,6 @@ +// Tests a very simple program. +// +// The features being tested is comparison +fn main(x: Field, y: Field) { + assert(x as u32 < y as u32); +} diff --git a/test_programs/execution_success/simple_mut/Nargo.toml b/test_programs/execution_success/simple_mut/Nargo.toml new file mode 100644 index 00000000000..c00e60bdbc0 --- /dev/null +++ b/test_programs/execution_success/simple_mut/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "simple_mut" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/simple_mut/Prover.toml b/test_programs/execution_success/simple_mut/Prover.toml new file mode 100644 index 00000000000..7d4290a117a --- /dev/null +++ b/test_programs/execution_success/simple_mut/Prover.toml @@ -0,0 +1 @@ +x = 1 diff --git a/test_programs/execution_success/simple_mut/src/main.nr b/test_programs/execution_success/simple_mut/src/main.nr new file mode 100644 index 00000000000..d0715dbafe0 --- /dev/null +++ b/test_programs/execution_success/simple_mut/src/main.nr @@ -0,0 +1,6 @@ +// A simple program to test mutable variables +fn main(x: Field) -> pub Field { + let mut y = 2; + y += x; + y +} diff --git a/test_programs/execution_success/simple_not/Nargo.toml b/test_programs/execution_success/simple_not/Nargo.toml new file mode 100644 index 00000000000..52c86b36efb --- /dev/null +++ b/test_programs/execution_success/simple_not/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "simple_not" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/simple_not/Prover.toml b/test_programs/execution_success/simple_not/Prover.toml new file mode 100644 index 00000000000..b3accc9dd32 --- /dev/null +++ b/test_programs/execution_success/simple_not/Prover.toml @@ -0,0 +1 @@ +x = false \ No newline at end of file diff --git a/test_programs/execution_success/simple_not/src/main.nr b/test_programs/execution_success/simple_not/src/main.nr new file mode 100644 index 00000000000..ba172625fe4 --- /dev/null +++ b/test_programs/execution_success/simple_not/src/main.nr @@ -0,0 +1,4 @@ +// A simple program for testing the NOT op +fn main(x: bool) -> pub bool { + !x +} diff --git a/test_programs/execution_success/simple_print/Nargo.toml b/test_programs/execution_success/simple_print/Nargo.toml new file mode 100644 index 00000000000..cd8422ac482 --- /dev/null +++ b/test_programs/execution_success/simple_print/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "simple_print" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/simple_print/Prover.toml b/test_programs/execution_success/simple_print/Prover.toml new file mode 100644 index 00000000000..2c1854573a4 --- /dev/null +++ b/test_programs/execution_success/simple_print/Prover.toml @@ -0,0 +1,2 @@ +x = 1 +y = 2 diff --git a/test_programs/execution_success/simple_print/src/main.nr b/test_programs/execution_success/simple_print/src/main.nr new file mode 100644 index 00000000000..938f770c5a5 --- /dev/null +++ b/test_programs/execution_success/simple_print/src/main.nr @@ -0,0 +1,6 @@ +// Simple program for testing the logging +// of single witnesses and witness arrays. +fn main(x: Field, y: pub Field) { + std::println(x); + std::println([x, y]); +} diff --git a/test_programs/execution_success/simple_program_addition/Nargo.toml b/test_programs/execution_success/simple_program_addition/Nargo.toml new file mode 100644 index 00000000000..28967a28a55 --- /dev/null +++ b/test_programs/execution_success/simple_program_addition/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "simple_program_addition" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/simple_program_addition/Prover.toml b/test_programs/execution_success/simple_program_addition/Prover.toml new file mode 100644 index 00000000000..07890234a19 --- /dev/null +++ b/test_programs/execution_success/simple_program_addition/Prover.toml @@ -0,0 +1 @@ +x = "3" diff --git a/test_programs/execution_success/simple_program_addition/src/main.nr b/test_programs/execution_success/simple_program_addition/src/main.nr new file mode 100644 index 00000000000..0390d79e83b --- /dev/null +++ b/test_programs/execution_success/simple_program_addition/src/main.nr @@ -0,0 +1,5 @@ +// The feature being tested is handling of +// a binary operation. +fn main(x: Field) -> pub Field { + x + 1 +} diff --git a/test_programs/execution_success/simple_radix/Nargo.toml b/test_programs/execution_success/simple_radix/Nargo.toml new file mode 100644 index 00000000000..12cbc8da1d3 --- /dev/null +++ b/test_programs/execution_success/simple_radix/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "simple_radix" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/simple_radix/Prover.toml b/test_programs/execution_success/simple_radix/Prover.toml new file mode 100644 index 00000000000..1ddfb7dc8e4 --- /dev/null +++ b/test_programs/execution_success/simple_radix/Prover.toml @@ -0,0 +1 @@ +x = 2 \ No newline at end of file diff --git a/test_programs/execution_success/simple_radix/src/main.nr b/test_programs/execution_success/simple_radix/src/main.nr new file mode 100644 index 00000000000..b905d2e533e --- /dev/null +++ b/test_programs/execution_success/simple_radix/src/main.nr @@ -0,0 +1,7 @@ +// Simple program to test to_radix +fn main(x: Field) { + let bits: [u1; 3] = x.to_le_bits(); + assert(bits[0] == 0); + assert(bits[1] == 1); + assert(bits[2] == 0); +} diff --git a/test_programs/execution_success/simple_shield/Nargo.toml b/test_programs/execution_success/simple_shield/Nargo.toml new file mode 100644 index 00000000000..7e9579b0af4 --- /dev/null +++ b/test_programs/execution_success/simple_shield/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "simple_shield" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/simple_shield/Prover.toml b/test_programs/execution_success/simple_shield/Prover.toml new file mode 100644 index 00000000000..7878e4b8281 --- /dev/null +++ b/test_programs/execution_success/simple_shield/Prover.toml @@ -0,0 +1,11 @@ +# Random test key +priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" +note_root = "0x02278fc806225cd696bd502049f7bb98624536de56d09343f8a26ac1876b23a0" +index = "0" +note_hash_path = [ + "0x1cdcf02431ba623767fe389337d011df1048dcc24b98ed81cec97627bab454a0", + "0x0b5e9666e7323ce925c28201a97ddf4144ac9d148448ed6f49f9008719c1b85b", + "0x22ec636f8ad30ef78c42b7fe2be4a4cacf5a445cfb5948224539f59a11d70775", +] +to_pubkey_x = "0x0000000000000000000000000000000000000000000000000000000000000001" +to_pubkey_y = "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c" diff --git a/test_programs/execution_success/simple_shield/src/main.nr b/test_programs/execution_success/simple_shield/src/main.nr new file mode 100644 index 00000000000..35b50150986 --- /dev/null +++ b/test_programs/execution_success/simple_shield/src/main.nr @@ -0,0 +1,26 @@ +fn main( + // Public key of note + // all notes have the same denomination + priv_key: Field, + // Merkle membership proof + note_root: pub Field, + index: Field, + note_hash_path: [Field; 3], + // Receiver public key + to_pubkey_x: Field, + to_pubkey_y: Field, +) -> pub [Field; 2] { + let priv_key_as_scalar = std::embedded_curve_ops::EmbeddedCurveScalar { lo: priv_key, hi: 0 }; + // Compute public key from private key to show ownership + let pubkey = std::embedded_curve_ops::fixed_base_scalar_mul(priv_key_as_scalar); + // Compute input note commitment + let note_commitment = std::hash::pedersen_commitment([pubkey.x, pubkey.y]); + // Compute input note nullifier + let nullifier = std::hash::pedersen_commitment([note_commitment.x, index, priv_key]); + // Compute output note nullifier + let receiver_note_commitment = std::hash::pedersen_commitment([to_pubkey_x, to_pubkey_y]); + // Check that the input note nullifier is in the root + assert(note_root == std::merkle::compute_merkle_root(note_commitment.x, index, note_hash_path)); + + [nullifier.x, receiver_note_commitment.x] +} diff --git a/test_programs/execution_success/simple_shift_left_right/Nargo.toml b/test_programs/execution_success/simple_shift_left_right/Nargo.toml new file mode 100644 index 00000000000..2e75d5feada --- /dev/null +++ b/test_programs/execution_success/simple_shift_left_right/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "simple_shift_left_right" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/simple_shift_left_right/Prover.toml b/test_programs/execution_success/simple_shift_left_right/Prover.toml new file mode 100644 index 00000000000..07890234a19 --- /dev/null +++ b/test_programs/execution_success/simple_shift_left_right/Prover.toml @@ -0,0 +1 @@ +x = "3" diff --git a/test_programs/execution_success/simple_shift_left_right/src/main.nr b/test_programs/execution_success/simple_shift_left_right/src/main.nr new file mode 100644 index 00000000000..f5d06eff25a --- /dev/null +++ b/test_programs/execution_success/simple_shift_left_right/src/main.nr @@ -0,0 +1,8 @@ +// Tests a very simple program. +// +// The features being tested are left and right shifts. +fn main(x: u32) { + let z = x >> 4; + let t = x << 4; + assert(z == t >> 8); +} diff --git a/test_programs/execution_success/single_verify_proof/Nargo.toml b/test_programs/execution_success/single_verify_proof/Nargo.toml new file mode 100644 index 00000000000..9dfbbcb9c1d --- /dev/null +++ b/test_programs/execution_success/single_verify_proof/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "single_verify_proof" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/single_verify_proof/Prover.toml b/test_programs/execution_success/single_verify_proof/Prover.toml new file mode 100644 index 00000000000..27b3ebc0c35 --- /dev/null +++ b/test_programs/execution_success/single_verify_proof/Prover.toml @@ -0,0 +1,4 @@ +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"] \ No newline at end of file diff --git a/test_programs/execution_success/single_verify_proof/src/main.nr b/test_programs/execution_success/single_verify_proof/src/main.nr new file mode 100644 index 00000000000..6073087d644 --- /dev/null +++ b/test_programs/execution_success/single_verify_proof/src/main.nr @@ -0,0 +1,14 @@ +// This circuit aggregates one proof from `assert_statement`. +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, +) { + std::verify_proof(verification_key, proof, public_inputs, key_hash); +} 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..4a83b739523 --- /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); + std::println(var1); +} diff --git a/test_programs/execution_success/slice_dynamic_index/Nargo.toml b/test_programs/execution_success/slice_dynamic_index/Nargo.toml new file mode 100644 index 00000000000..a02faeae27a --- /dev/null +++ b/test_programs/execution_success/slice_dynamic_index/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "slice_dynamic_index" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/slice_dynamic_index/Prover.toml b/test_programs/execution_success/slice_dynamic_index/Prover.toml new file mode 100644 index 00000000000..0e5dfd5638d --- /dev/null +++ b/test_programs/execution_success/slice_dynamic_index/Prover.toml @@ -0,0 +1 @@ +x = "5" diff --git a/test_programs/execution_success/slice_dynamic_index/src/main.nr b/test_programs/execution_success/slice_dynamic_index/src/main.nr new file mode 100644 index 00000000000..2ab633eb98c --- /dev/null +++ b/test_programs/execution_success/slice_dynamic_index/src/main.nr @@ -0,0 +1,308 @@ +fn main(x: Field) { + // The parameters to this function must come directly from witness values (inputs to main). + regression_dynamic_slice_index(x - 1, x - 4); +} + +fn regression_dynamic_slice_index(x: Field, y: Field) { + let mut slice = &[]; + for i in 0..5 { + slice = slice.push_back(i as Field); + } + assert(slice.len() == 5); + + dynamic_slice_index_set_if(slice, x, y); + dynamic_slice_index_set_else(slice, x, y); + dynamic_slice_index_set_nested_if_else_else(slice, x, y); + dynamic_slice_index_set_nested_if_else_if(slice, x, y + 1); + dynamic_slice_index_if(slice, x); + dynamic_array_index_if([0, 1, 2, 3, 4], x); + dynamic_slice_index_else(slice, x); + + dynamic_slice_merge_if(slice, x); + dynamic_slice_merge_else(slice, x); + dynamic_slice_merge_two_ifs(slice, x); + dynamic_slice_merge_mutate_between_ifs(slice, x, y); + dynamic_slice_merge_push_then_pop(slice, x, y); +} + +fn dynamic_slice_index_set_if(mut slice: [Field], x: Field, y: Field) { + assert(slice[x] == 4); + assert(slice[y] == 1); + slice[y] = 0; + assert(slice[x] == 4); + assert(slice[1] == 0); + if x as u32 < 10 { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + slice[x - 1] = slice[x]; + } else { + slice[x] = 0; + } + assert(slice[3] == 2); + assert(slice[4] == 2); +} + +fn dynamic_slice_index_set_else(mut slice: [Field], x: Field, y: Field) { + assert(slice[x] == 4); + assert(slice[y] == 1); + slice[y] = 0; + assert(slice[x] == 4); + assert(slice[1] == 0); + if x as u32 > 10 { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + slice[x - 1] = slice[x]; + } else { + slice[x] = 0; + } + assert(slice[4] == 0); +} +// This tests the case of missing a store instruction in the else branch +// of merging slices +fn dynamic_slice_index_if(mut slice: [Field], x: Field) { + if x as u32 < 10 { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + } else { + assert(slice[x] == 0); + } + assert(slice[4] == 2); +} + +fn dynamic_array_index_if(mut array: [Field; 5], x: Field) { + if x as u32 < 10 { + assert(array[x] == 4); + array[x] = array[x] - 2; + } else { + assert(array[x] == 0); + } + assert(array[4] == 2); +} +// This tests the case of missing a store instruction in the then branch +// of merging slices +fn dynamic_slice_index_else(mut slice: [Field], x: Field) { + if x as u32 > 10 { + assert(slice[x] == 0); + } else { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + } + assert(slice[4] == 2); +} + +fn dynamic_slice_merge_if(mut slice: [Field], x: Field) { + if x as u32 < 10 { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + + slice = slice.push_back(10); + // Having an array set here checks whether we appropriately + // handle a slice length that is not yet resolving to a constant + // during flattening + slice[x] = 10; + assert(slice[slice.len() - 1] == 10); + assert(slice.len() == 6); + + slice[x] = 20; + slice[x] = slice[x] + 10; + + slice = slice.push_front(11); + assert(slice[0] == 11); + assert(slice.len() == 7); + assert(slice[5] == 30); + + slice = slice.push_front(12); + assert(slice[0] == 12); + assert(slice.len() == 8); + assert(slice[6] == 30); + + let (popped_slice, last_elem) = slice.pop_back(); + assert(last_elem == 10); + assert(popped_slice.len() == 7); + + let (first_elem, rest_of_slice) = popped_slice.pop_front(); + assert(first_elem == 12); + assert(rest_of_slice.len() == 6); + + slice = rest_of_slice.insert(x 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 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; + + assert(removed_elem == 1); + assert(slice.len() == 6); + } else { + assert(slice[x] == 0); + slice = slice.push_back(20); + } + + assert(slice.len() == 6); + assert(slice[slice.len() - 1] == 30); +} + +fn dynamic_slice_merge_else(mut slice: [Field], x: Field) { + if x as u32 > 10 { + assert(slice[x] == 0); + slice[x] = 2; + } else { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + slice = slice.push_back(10); + } + assert(slice.len() == 6); + assert(slice[slice.len() - 1] == 10); + + slice = slice.push_back(20); + assert(slice.len() == 7); + assert(slice[slice.len() - 1] == 20); +} + +fn dynamic_slice_index_set_nested_if_else_else(mut slice: [Field], x: Field, y: Field) { + assert(slice[x] == 4); + assert(slice[y] == 1); + slice[y] = 0; + assert(slice[x] == 4); + assert(slice[1] == 0); + if x as u32 < 10 { + slice[x] = slice[x] - 2; + if y != 1 { + slice[x] = slice[x] + 20; + } else { + if x == 5 { + // We should not hit this case + assert(slice[x] == 22); + } else { + slice[x] = 10; + slice = slice.push_back(15); + assert(slice.len() == 6); + } + assert(slice[4] == 10); + } + } else { + slice[x] = 0; + } + assert(slice[4] == 10); + assert(slice.len() == 6); + assert(slice[slice.len() - 1] == 15); + + slice = slice.push_back(20); + assert(slice.len() == 7); + assert(slice[slice.len() - 1] == 20); +} + +fn dynamic_slice_index_set_nested_if_else_if(mut slice: [Field], x: Field, y: Field) { + assert(slice[x] == 4); + assert(slice[y] == 2); + slice[y] = 0; + assert(slice[x] == 4); + assert(slice[2] == 0); + if x as u32 < 10 { + slice[x] = slice[x] - 2; + // TODO: this panics as we have a load for the slice in flattening + if y == 1 { + slice[x] = slice[x] + 20; + } else { + if x == 4 { + slice[x] = 5; + } + assert(slice[4] == 5); + } + } else { + slice[x] = 0; + } + assert(slice[4] == 5); +} + +fn dynamic_slice_merge_two_ifs(mut slice: [Field], x: Field) { + if x as u32 > 10 { + assert(slice[x] == 0); + slice[x] = 2; + } else { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + slice = slice.push_back(10); + } + + assert(slice.len() == 6); + assert(slice[slice.len() - 1] == 10); + + if x == 20 { + slice = slice.push_back(20); + } + + slice = slice.push_back(15); + + assert(slice.len() == 7); + assert(slice[slice.len() - 1] == 15); + + slice = slice.push_back(20); + assert(slice.len() == 8); + assert(slice[slice.len() - 1] == 20); +} + +fn dynamic_slice_merge_mutate_between_ifs(mut slice: [Field], x: Field, y: Field) { + if x != y { + slice[x] = 50; + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice[x] = slice[x] - 2; + slice = slice.push_back(x); + } + + slice = slice.push_back(30); + assert(slice.len() == 8); + + if x == 20 { + slice = slice.push_back(20); + } + + slice = slice.push_back(15); + + if x != 20 { + slice = slice.push_back(50); + } + + slice = slice.push_back(60); + assert(slice.len() == 11); + assert(slice[x] == 50); + assert(slice[slice.len() - 4] == 30); + assert(slice[slice.len() - 3] == 15); + assert(slice[slice.len() - 2] == 50); + assert(slice[slice.len() - 1] == 60); +} + +fn dynamic_slice_merge_push_then_pop(mut slice: [Field], x: Field, y: Field) { + if x != y { + slice[x] = 5; + slice = slice.push_back(y); + slice = slice.push_back(x); + assert(slice.len() == 7); + + let (popped_slice, elem) = slice.pop_back(); + assert(slice.len() == 7); + assert(elem == x); + slice = popped_slice; + } else { + slice = slice.push_back(x); + } + + slice = slice.push_back(30); + assert(slice.len() == 7); + + if x == 20 { + slice = slice.push_back(20); + } + + let (slice, elem) = slice.pop_back(); + assert(elem == 30); + + let (_, elem) = slice.pop_back(); + assert(elem == y); +} + diff --git a/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/slice_regex/Nargo.toml b/test_programs/execution_success/slice_regex/Nargo.toml new file mode 100644 index 00000000000..ac95636c74a --- /dev/null +++ b/test_programs/execution_success/slice_regex/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "slice_regex" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/slice_regex/src/main.nr b/test_programs/execution_success/slice_regex/src/main.nr new file mode 100644 index 00000000000..67901f10f29 --- /dev/null +++ b/test_programs/execution_success/slice_regex/src/main.nr @@ -0,0 +1,808 @@ +struct Match { + succeeded: bool, + match_ends: u32, + leftover: [u8], +} + +impl Match { + fn empty(leftover: [u8]) -> Self { + Match { succeeded: true, match_ends: 0, leftover } + } +} + +impl Eq for Match { + fn eq(self, other: Self) -> bool { + (self.succeeded == other.succeeded) & (self.match_ends == other.match_ends) + // (self.leftover == other.leftover) + } +} + +// TODO: load match into str and assert that it's the correct length +// impl From for str + +trait Regex { + fn find_match(self, input: [u8]) -> Match; +} + +// Empty +impl Regex for () { + fn find_match(_self: Self, input: [u8]) -> Match { + Match::empty(input) + } +} + +// Exact +impl Regex for str { + fn find_match(self, input: [u8]) -> Match { + let mut leftover = input; + let mut matches_input = true; + let self_as_bytes = self.as_bytes(); + for c in self_as_bytes { + if leftover.len() != 0 { + let (first_elem, popped_slice) = leftover.pop_front(); + leftover = popped_slice; + matches_input &= first_elem == c; + } else { + matches_input = false; + } + } + if matches_input { + Match { succeeded: true, match_ends: self_as_bytes.len(), leftover } + } else { + Match { succeeded: false, match_ends: 0, leftover: input } + } + } +} + +// And +impl Regex for (T, U) +where + T: Regex, + U: Regex, +{ + fn find_match(self, input: [u8]) -> Match { + let lhs_result = self.0.find_match(input); + if lhs_result.succeeded { + let rhs_result = self.1.find_match(lhs_result.leftover); + if rhs_result.succeeded { + Match { + succeeded: true, + match_ends: lhs_result.match_ends + rhs_result.match_ends, + leftover: rhs_result.leftover, + } + } else { + Match { succeeded: false, match_ends: 0, leftover: input } + } + } else { + Match { succeeded: false, match_ends: 0, leftover: input } + } + } +} + +// N T's: (T, (T, (T, T))) +struct Repeated { + inner: T, +} + +impl Regex for Repeated +where + T: Regex, +{ + fn find_match(self, input: [u8]) -> Match { + let mut result = Match::empty(input); + for _ in 0..N { + if result.succeeded { + let next_result = self.inner.find_match(result.leftover); + result = Match { + succeeded: next_result.succeeded, + match_ends: result.match_ends + next_result.match_ends, + leftover: next_result.leftover, + }; + } + } + result + } +} + +struct Or { + lhs: T, + rhs: U, +} + +impl Regex for Or +where + T: Regex, + U: Regex, +{ + fn find_match(self, input: [u8]) -> Match { + let lhs_result = self.lhs.find_match(input); + if lhs_result.succeeded { + lhs_result + } else { + self.rhs.find_match(input) + } + } +} + +struct Question { + inner: T, +} + +impl Regex for Question +where + T: Regex, +{ + fn find_match(self, input: [u8]) -> Match { + Or { lhs: self.inner, rhs: () }.find_match(input) + } +} + +// 0 <= num_matches <= N +struct Star { + inner: T, +} + +impl Regex for Star +where + T: Regex, +{ + fn find_match(self, input: [u8]) -> Match { + let regex: Repeated<_, N> = Repeated { inner: Question { inner: self.inner } }; + regex.find_match(input) + } +} + +// 0 < num_matches <= N +struct Plus { + inner: T, +} + +impl Regex for Plus +where + T: Regex, +{ + fn find_match(self, input: [u8]) -> Match { + std::static_assert(N_PRED + 1 == N, "N - 1 != N_PRED"); + let star: Star = Star { inner: self.inner }; + (self.inner, star).find_match(input) + } +} + +fn main() { + // gr(a|e)y + let graey_regex = ("gr", (Or { lhs: "a", rhs: "e" }, "y")); + + // NOTE: leftover ignored in Eq: Match + let result = graey_regex.find_match("gray".as_bytes().as_slice()); + println(result); + assert_eq(result, Match { succeeded: true, match_ends: 4, leftover: &[] }); + + // NOTE: leftover ignored in Eq: Match + let result = graey_regex.find_match("grey".as_bytes().as_slice()); + println(result); + assert_eq(result, Match { succeeded: true, match_ends: 4, leftover: &[] }); + + // colou?r + let colour_regex = ("colo", (Question { inner: "u" }, "r")); + + let result = colour_regex.find_match("color".as_bytes().as_slice()); + println(result); + assert_eq(result, Match { succeeded: true, match_ends: 5, leftover: &[] }); + + let result = colour_regex.find_match("colour".as_bytes().as_slice()); + println(result); + assert_eq(result, Match { succeeded: true, match_ends: 6, leftover: &[] }); + + // parse the empty string three times + // EMPTY{3} + let three_empties_regex: Repeated<(), 3> = Repeated { inner: () }; + + let result = three_empties_regex.find_match("111".as_bytes().as_slice()); + println(result); + assert_eq(result, Match { succeeded: true, match_ends: 0, leftover: &[] }); + + // 1{0} + let zero_ones_regex: Repeated, 0> = Repeated { inner: "1" }; + + let result = zero_ones_regex.find_match("111".as_bytes().as_slice()); + println(result); + assert_eq(result, Match { succeeded: true, match_ends: 0, leftover: &[] }); + + // 1{1} + let one_ones_regex: Repeated, 1> = Repeated { inner: "1" }; + + let result = one_ones_regex.find_match("111".as_bytes().as_slice()); + println(result); + assert_eq(result, Match { succeeded: true, match_ends: 1, leftover: &[] }); + + // 1{2} + let two_ones_regex: Repeated, 2> = Repeated { inner: "1" }; + + let result = two_ones_regex.find_match("111".as_bytes().as_slice()); + println(result); + assert_eq(result, Match { succeeded: true, match_ends: 2, leftover: &[] }); + + // 1{3} + let three_ones_regex: Repeated, 3> = Repeated { inner: "1" }; + + let result = three_ones_regex.find_match("1111".as_bytes().as_slice()); + println(result); + assert_eq(result, Match { succeeded: true, match_ends: 3, leftover: &[] }); + // TODO(https://github.com/noir-lang/noir/issues/6285): re-enable these cases and complete the test using array_regex below + // + // // 1* + // let ones_regex: Star, 5> = Star { inner: "1" }; + // + // let result = ones_regex.find_match("11000".as_bytes().as_slice()); + // println(result); + // assert_eq(result, Match { succeeded: true, match_ends: 2, leftover: &[] }); + // + // let result = ones_regex.find_match("11".as_bytes().as_slice()); + // println(result); + // assert_eq(result, Match { succeeded: true, match_ends: 2, leftover: &[] }); + // + // let result = ones_regex.find_match("111111".as_bytes().as_slice()); + // println(result); + // assert_eq(result, Match { succeeded: true, match_ends: 5, leftover: &[] }); + // + // + // // 1+ + // let nonempty_ones_regex: Plus, 5, 4> = Plus { inner: "1" }; + // + // let result = nonempty_ones_regex.find_match("111111".as_bytes().as_slice()); + // println(result); + // assert_eq(result, Match { succeeded: true, match_ends: 5, leftover: &[] }); + // + // // 2^n-1 in binary: 1+0 + // let pred_pow_two_regex = (nonempty_ones_regex, "0"); + // + // let result = pred_pow_two_regex.find_match("1110".as_bytes().as_slice()); + // println(result); + // assert_eq(result, Match { succeeded: true, match_ends: 3, leftover: &[] }); + // + // // (0|1)* + // let binary_regex: Star, str<1>>, 5> = Star { inner: Or { lhs: "0", rhs: "1" } }; + // + // let result = binary_regex.find_match("110100".as_bytes().as_slice()); + // println(result); + // assert_eq(result, Match { succeeded: true, match_ends: 5, leftover: &[] }); + // + // // even numbers in binary: 1(0|1)*0 + // let even_binary_regex = ("1", (binary_regex, "0")); + // + // let result = even_binary_regex.find_match("1111110".as_bytes().as_slice()); + // println(result); + // assert_eq(result, Match { succeeded: true, match_ends: 6, leftover: &[] }); + // 2-letter capitalized words: [A-Z][a-z] + // numbers: \d+ + // [0-9]+ + // words: \w+ + // [a-Z]+ + // adapted URL parser: (https?:\/\/)?([\da-z.\-]+)\.([a-z.]+)([\/\w \.\-]*)*\/? + // // panics (at compile time) when input string is too short + // let foo_regex = ( + // "colo", + // ( + // Question { + // inner: "u", + // }, + // "r" + // ) + // ); + // + // let result = foo_regex.find_match("colo".as_bytes().as_slice()); + // println(result); + // assert_eq(result, Match { + // succeeded: true, + // match_ends: 4, + // leftover: &[], + // }); +} + +// TODO +// array_regex execution_success test: +// use to complete test once https://github.com/noir-lang/noir/issues/6285 is resolved +// +// // offset <= len <= N +// struct Bvec { +// inner: [T; N], +// +// // elements at indices < offset are zero +// offset: u32, +// +// // elements at indices >= len are zero +// len: u32, +// } +// +// impl Eq for Bvec where T: Eq { +// fn eq(self, other: Self) -> bool { +// (self.inner == other.inner) & +// (self.offset == other.offset) & +// (self.len == other.len) +// } +// } +// +// impl Bvec { +// fn empty() -> Self { +// Self { inner: [std::mem::zeroed(); N], offset: 0, len: 0 } +// } +// +// fn new(array: [T; N]) -> Self { +// let mut result = Bvec::empty(); +// for x in array { +// result = result.push(x); +// } +// result +// } +// +// // pushing when len == N is a no-op +// fn push(self, x: T) -> Self { +// let mut inner = self.inner; +// let mut len = self.len; +// if self.len < N { +// inner[self.len] = x; +// len += 1; +// } +// +// Self { inner, offset: self.offset, len } +// } +// +// fn pop_front(self) -> (T, Self) { +// assert(self.offset <= self.inner.len()); +// assert(self.len != 0); +// +// let first_elem = self.inner[self.offset]; +// let popped_slice = Self { inner: self.inner, offset: self.offset + 1, len: self.len - 1 }; +// +// (first_elem, popped_slice) +// } +// } +// +// struct Match { +// succeeded: bool, +// match_ends: u32, +// leftover: Bvec, +// } +// +// impl Match { +// fn empty(leftover: Bvec) -> Self { +// Match { succeeded: true, match_ends: 0, leftover } +// } +// +// fn failed(leftover: Bvec) -> Self { +// Match { succeeded: false, match_ends: 0, leftover } +// } +// } +// +// impl Eq for Match { +// fn eq(self, other: Self) -> bool { +// (self.succeeded == other.succeeded) & +// (self.match_ends == other.match_ends) & +// (self.leftover == other.leftover) +// } +// } +// +// // TODO: load match into str and assert that it's the correct length +// // impl From for str +// +// trait Regex { +// // Perform a match without backtracking +// fn find_match(self, input: Bvec) -> Match; +// } +// +// // Empty +// impl Regex for () { +// fn find_match(_self: Self, input: Bvec) -> Match { +// Match::empty(input) +// } +// } +// +// // Exact +// impl Regex for str { +// fn find_match(self, input: Bvec) -> Match { +// let mut leftover = input; +// let mut matches_input = true; +// let self_as_bytes = self.as_bytes(); +// for c in self_as_bytes { +// if leftover.len != 0 { +// let (first_elem, popped_slice) = leftover.pop_front(); +// leftover = popped_slice; +// matches_input &= first_elem == c; +// } else { +// matches_input = false; +// } +// } +// if matches_input { +// Match { +// succeeded: true, +// match_ends: self_as_bytes.len(), +// leftover, +// } +// } else { +// Match { +// succeeded: false, +// match_ends: 0, +// leftover: input, +// } +// } +// } +// } +// +// // And +// impl Regex for (T, U) where T: Regex, U: Regex { +// fn find_match(self, input: Bvec) -> Match { +// let lhs_result = self.0.find_match(input); +// if lhs_result.succeeded { +// let rhs_result = self.1.find_match(lhs_result.leftover); +// if rhs_result.succeeded { +// Match { +// succeeded: true, +// match_ends: lhs_result.match_ends + rhs_result.match_ends, +// leftover: rhs_result.leftover, +// } +// } else { +// Match { +// succeeded: false, +// match_ends: 0, +// leftover: input, +// } +// } +// } else { +// Match { +// succeeded: false, +// match_ends: 0, +// leftover: input, +// } +// } +// } +// } +// +// // N T's: (T, (T, (T, T))) +// struct Repeated { +// inner: T, +// } +// +// impl Regex for Repeated where T: Regex { +// fn find_match(self, input: Bvec) -> Match { +// let mut result = Match::empty(input); +// for _ in 0..M { +// if result.succeeded { +// let next_result = self.inner.find_match(result.leftover); +// result = Match { +// succeeded: next_result.succeeded, +// match_ends: result.match_ends + next_result.match_ends, +// leftover: next_result.leftover, +// }; +// } +// } +// result +// } +// } +// +// struct Or { +// lhs: T, +// rhs: U, +// } +// +// impl Regex for Or where T: Regex, U: Regex { +// fn find_match(self, input: Bvec) -> Match { +// let lhs_result = self.lhs.find_match(input); +// if lhs_result.succeeded { +// lhs_result +// } else { +// self.rhs.find_match(input) +// } +// } +// } +// +// struct Question { +// inner: T, +// } +// +// impl Regex for Question where T: Regex { +// fn find_match(self, input: Bvec) -> Match { +// Or { +// lhs: self.inner, +// rhs: (), +// }.find_match(input) +// } +// } +// +// // 0 <= num_matches <= N +// struct Star { +// inner: T, +// } +// +// impl Regex for Star where T: Regex { +// fn find_match(self, input: Bvec) -> Match { +// let regex: Repeated<_, M> = Repeated { +// inner: Question { inner: self.inner }, +// }; +// regex.find_match(input) +// } +// } +// +// // 0 < num_matches <= N +// struct Plus { +// inner: T, +// } +// +// impl Regex for Plus where T: Regex { +// fn find_match(self, input: Bvec) -> Match { +// std::static_assert(M_PRED + 1 == M, "M - 1 != M_PRED"); +// let star: Star = Star { inner: self.inner }; +// ( +// self.inner, +// star +// ).find_match(input) +// } +// } +// +// // Repeated is to (,) as AnyOf is to Or +// struct AnyOf { +// inner: [T; N], +// } +// +// impl Regex for AnyOf where T: Regex { +// fn find_match(self, input: Bvec) -> Match { +// let mut result = Match::failed(input); +// for i in 0..M { +// if !result.succeeded { +// result = self.inner[i].find_match(result.leftover); +// } +// } +// result +// } +// } +// +// fn reverse_array(input: [T; N]) -> [T; N] { +// let mut output = [std::mem::zeroed(); N]; +// for i in 0..N { +// output[i] = input[N - (i + 1)]; +// } +// output +// } +// +// fn main() { +// assert_eq(reverse_array([1, 2, 3, 4]), [4, 3, 2, 1]); +// +// let mut xs: Bvec = Bvec::empty(); +// +// xs = xs.push(0); +// assert_eq(xs, Bvec { inner: [0, 0, 0], offset: 0, len: 1 }); +// +// xs = xs.push(1); +// assert_eq(xs, Bvec { inner: [0, 1, 0], offset: 0, len: 2 }); +// +// xs = xs.push(2); +// assert_eq(xs, Bvec { inner: [0, 1, 2], offset: 0, len: 3 }); +// +// xs = xs.push(3); +// assert_eq(xs, Bvec { inner: [0, 1, 2], offset: 0, len: 3 }); +// +// let ys = Bvec::new([0, 1, 2]); +// assert_eq(xs, ys); +// +// // test that pop_front gives all contents, in order, +// // followed by std::mem::zeroed() +// println(xs); +// let (x, new_xs) = xs.pop_front(); +// assert_eq(x, 0); +// +// xs = new_xs; +// println(xs); +// let (x, new_xs) = xs.pop_front(); +// assert_eq(x, 1); +// +// xs = new_xs; +// println(xs); +// let (x, new_xs) = xs.pop_front(); +// assert_eq(x, 2); +// +// xs = new_xs; +// println(xs); +// if xs.len != 0 { +// let (x, _new_xs) = xs.pop_front(); +// assert_eq(x, std::mem::zeroed()); +// } +// +// assert_eq(new_xs, Bvec { inner: [0, 1, 2], offset: 3, len: 0 }); +// +// // gr(a|e)y +// let graey_regex = ("gr", (Or { lhs: "a", rhs: "e" }, "y")); +// +// let result = graey_regex.find_match(Bvec::new("gray".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 4); +// assert_eq(result.leftover.len, 0); +// +// let result = graey_regex.find_match(Bvec::new("grey".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 4); +// assert_eq(result.leftover.len, 0); +// +// // colou?r +// let colour_regex = ("colo", (Question { inner: "u" }, "r")); +// +// let result = colour_regex.find_match(Bvec::new("color".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 5); +// assert_eq(result.leftover.len, 0); +// +// let result = colour_regex.find_match(Bvec::new("colour".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 6); +// assert_eq(result.leftover.len, 0); +// +// // parse the empty string three times +// // EMPTY{3} +// let three_empties_regex: Repeated<(), 3> = Repeated { inner: () }; +// +// let result = three_empties_regex.find_match(Bvec::new("111".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 0); +// assert_eq(result.leftover.len, 3); +// +// // 1{0} +// let zero_ones_regex: Repeated, 0> = Repeated { inner: "1" }; +// +// let result = zero_ones_regex.find_match(Bvec::new("111".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 0); +// assert_eq(result.leftover.len, 3); +// +// // 1{1} +// let one_ones_regex: Repeated, 1> = Repeated { inner: "1" }; +// +// let result = one_ones_regex.find_match(Bvec::new("111".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 1); +// assert_eq(result.leftover.len, 2); +// +// // 1{2} +// let two_ones_regex: Repeated, 2> = Repeated { inner: "1" }; +// +// let result = two_ones_regex.find_match(Bvec::new("111".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 2); +// assert_eq(result.leftover.len, 1); +// +// // 1{3} +// let three_ones_regex: Repeated, 3> = Repeated { inner: "1" }; +// +// let result = three_ones_regex.find_match(Bvec::new("1111".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 3); +// assert_eq(result.leftover.len, 1); +// +// // 1* +// let ones_regex: Star, 5> = Star { inner: "1" }; +// +// let result = ones_regex.find_match(Bvec::new("11000".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 2); +// assert_eq(result.leftover.len, 3); +// +// let result = ones_regex.find_match(Bvec::new("11".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 2); +// assert_eq(result.leftover.len, 0); +// +// let result = ones_regex.find_match(Bvec::new("111111".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 5); +// assert_eq(result.leftover.len, 1); +// +// // 1+ +// let nonempty_ones_regex: Plus, 5, 4> = Plus { inner: "1" }; +// +// let result = nonempty_ones_regex.find_match(Bvec::new("111111".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 5); +// assert_eq(result.leftover.len, 1); +// +// // 2^n-1 in binary: 1+0 +// let pred_pow_two_regex = (nonempty_ones_regex, "0"); +// +// let result = pred_pow_two_regex.find_match(Bvec::new("1110".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 4); +// assert_eq(result.leftover.len, 0); +// +// // (0|1)* +// let binary_regex: Star, str<1>>, 5> = Star { inner: Or { lhs: "0", rhs: "1" } }; +// +// let result = binary_regex.find_match(Bvec::new("110100".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 5); +// assert_eq(result.leftover.len, 1); +// +// // even numbers in binary: 1(0|1)*0 +// let even_binary_regex = ("1", (binary_regex, "0")); +// +// let result = even_binary_regex.find_match(Bvec::new("1111110".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 7); +// assert_eq(result.leftover.len, 0); +// +// // digit: \d+ +// // [0-9] +// let digit_regex = AnyOf { +// inner: [ +// "0", +// "1", +// "2", +// "3", +// "4", +// "5", +// "6", +// "7", +// "8", +// "9" +// ] +// }; +// +// let result = digit_regex.find_match(Bvec::new("157196345823795".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 1); +// assert_eq(result.leftover.len, 14); +// +// let result = digit_regex.find_match(Bvec::new("hi".as_bytes())); +// println(result); +// assert(!result.succeeded); +// assert_eq(result.match_ends, 0); +// assert_eq(result.leftover.len, 2); +// +// // digits: \d+ +// // [0-9]+ +// let digits_regex: Plus, 10>, 32, 31> = Plus { inner: digit_regex }; +// +// let result = digits_regex.find_match(Bvec::new("123456789012345".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 15); +// assert_eq(result.leftover.len, 0); +// +// let result = digits_regex.find_match(Bvec::new("123456789012345 then words".as_bytes())); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 15); +// assert_eq(result.leftover.len, 11); +// +// // multiples of 10 +// // apply to a reversed input string (because there isn't backtracking) +// // 0\d+ +// let backwards_mult_of_10_regex = ("0", digits_regex); +// +// let result = backwards_mult_of_10_regex.find_match(Bvec::new(reverse_array("1230".as_bytes()))); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 4); +// assert_eq(result.leftover.len, 0); +// +// let ten_pow_16: str<17> = "10000000000000000"; +// let result = backwards_mult_of_10_regex.find_match(Bvec::new(reverse_array(ten_pow_16.as_bytes()))); +// println(result); +// assert(result.succeeded); +// assert_eq(result.match_ends, 17); +// assert_eq(result.leftover.len, 0); +// // adapted URL parser: (https?:\/\/)?([\da-c.\-]+)\.([a-c.]+)([\/\w \.\-]*)*\/? +// } + diff --git a/test_programs/execution_success/slices/Nargo.toml b/test_programs/execution_success/slices/Nargo.toml new file mode 100644 index 00000000000..3eec413bc07 --- /dev/null +++ b/test_programs/execution_success/slices/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "slices" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/slices/Prover.toml b/test_programs/execution_success/slices/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/slices/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_success/slices/src/main.nr b/test_programs/execution_success/slices/src/main.nr new file mode 100644 index 00000000000..f1f2580d6c8 --- /dev/null +++ b/test_programs/execution_success/slices/src/main.nr @@ -0,0 +1,348 @@ +use std::slice; + +fn main(x: Field, y: pub Field) { + let mut slice = &[0; 2]; + assert(slice[0] == 0); + assert(slice[0] != 1); + slice[0] = x; + assert(slice[0] == x); + + let slice_plus_10 = slice.push_back(y); + assert(slice_plus_10[2] == 10); + assert(slice_plus_10[2] != 8); + assert(slice_plus_10.len() == 3); + + let mut new_slice = &[]; + for i in 0..5 { + new_slice = new_slice.push_back(i); + } + assert(new_slice.len() == 5); + + new_slice = new_slice.push_front(20); + assert(new_slice[0] == 20); + assert(new_slice.len() == 6); + + let (popped_slice, last_elem) = new_slice.pop_back(); + assert(last_elem == 4); + assert(popped_slice.len() == 5); + + let (first_elem, rest_of_slice) = popped_slice.pop_front(); + assert(first_elem == 20); + assert(rest_of_slice.len() == 4); + + new_slice = rest_of_slice.insert(2, 100); + assert(new_slice[2] == 100); + assert(new_slice[4] == 3); + assert(new_slice.len() == 5); + + let (remove_slice, removed_elem) = new_slice.remove(3); + assert(removed_elem == 2); + assert(remove_slice[3] == 3); + assert(remove_slice.len() == 4); + + let append = &[1, 2].append(&[3, 4, 5]); + assert(append.len() == 5); + assert(append[0] == 1); + assert(append[4] == 5); + + let mapped = &[1, 2].map(|x| x + 1); + assert_eq(mapped, &[2, 3]); + + assert_eq(&[1, 2, 3].fold(0, |acc, x| acc + x), 6); + assert_eq(&[1, 2, 3].reduce(|acc, x| acc + x), 6); + assert(&[2, 4, 6].all(|x| x > 0)); + assert(&[2, 4, 6].any(|x| x > 5)); + + regression_2083(); + // 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 = 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); + + let y = y.push_front((10, 11)); // [(10, 11), (1, 2), (3, 4), (5, 6)] + let y = y.push_front((12, 13)); // [(12, 13), (10, 11), (1, 2), (3, 4), (5, 6)] + assert(y[1].0 == 10); + + let y = y.insert(1, (55, 56)); // [(12, 13), (55, 56), (10, 11), (1, 2), (3, 4), (5, 6)] + assert(y[0].1 == 13); + assert(y[1].1 == 56); + assert(y[2].0 == 10); + + let (y, x) = y.remove(2); // [(12, 13), (55, 56), (1, 2), (3, 4), (5, 6)] + assert(y[2].0 == 1); + assert(x.0 == 10); + assert(x.1 == 11); + + let (x, y) = y.pop_front(); // [(55, 56), (1, 2), (3, 4), (5, 6)] + assert(y[0].0 == 55); + assert(x.0 == 12); + assert(x.1 == 13); + + let (y, x) = y.pop_back(); // [(55, 56), (1, 2), (3, 4)] + assert(y.len() == 3); + 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); + merge_slices_else(x); +} + +fn merge_slices_if(x: Field, y: Field) { + let slice = merge_slices_return(x, y); + assert(slice.len() == 3); + assert(slice[2] == 10); + + let slice = merge_slices_mutate(x, y); + assert(slice.len() == 4); + assert(slice[3] == 5); + + let slice = merge_slices_mutate_in_loop(x, y); + assert(slice.len() == 7); + assert(slice[6] == 4); + + let slice = merge_slices_mutate_two_ifs(x, y); + assert(slice.len() == 6); + assert(slice[3] == 5); + assert(slice[4] == 15); + assert(slice[5] == 30); + + let slice = merge_slices_mutate_between_ifs(x, y); + assert(slice.len() == 8); + assert(slice[3] == 5); + assert(slice[4] == 30); + assert(slice[5] == 15); + assert(slice[6] == 50); + assert(slice[7] == 60); + + merge_slices_push_then_pop(x, y); + + let slice = merge_slices_push_then_insert(x, y); + assert(slice.len() == 7); + assert(slice[1] == 50); + assert(slice[2] == 0); + assert(slice[5] == 30); + assert(slice[6] == 100); + + let slice = merge_slices_remove_between_ifs(x, y); + assert(slice.len() == 5); +} + +fn merge_slices_else(x: Field) { + let slice = merge_slices_return(x, 5); + assert(slice[0] == 0); + assert(slice[1] == 0); + assert(slice.len() == 2); + + let slice = merge_slices_mutate(x, 5); + assert(slice[2] == 5); + assert(slice.len() == 3); + + let slice = merge_slices_mutate_in_loop(x, 5); + assert(slice[2] == 5); + assert(slice.len() == 3); +} + +// Test returning a merged slice without a mutation +fn merge_slices_return(x: Field, y: Field) -> [Field] { + let slice = &[0; 2]; + if x != y { + if x != 20 { + slice.push_back(y) + } else { + slice + } + } 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]; + if x != y { + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice = slice.push_back(x); + } + 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]; + if x != y { + for i in 0..5 { + slice = slice.push_back(i as Field); + } + } else { + slice = slice.push_back(x); + } + slice +} + +fn merge_slices_mutate_two_ifs(x: Field, y: Field) -> [Field] { + let mut slice = &[0; 2]; + if x != y { + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice = slice.push_back(x); + } + + if x == 20 { + slice = slice.push_back(20); + } + + slice = slice.push_back(15); + slice = slice.push_back(30); + + slice +} + +fn merge_slices_mutate_between_ifs(x: Field, y: Field) -> [Field] { + let mut slice = &[0; 2]; + if x != y { + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice = slice.push_back(x); + } + + slice = slice.push_back(30); + + if x == 20 { + slice = slice.push_back(20); + } + + slice = slice.push_back(15); + + if x != 20 { + slice = slice.push_back(50); + } + + slice = slice.push_back(60); + + slice +} + +fn merge_slices_push_then_pop(x: Field, y: Field) { + let mut slice = &[0; 2]; + if x != y { + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice = slice.push_back(x); + } + + slice = slice.push_back(30); + + if x == 20 { + slice = slice.push_back(20); + } + + let (slice, elem) = slice.pop_back(); + assert(slice.len() == 4); + assert(elem == 30); + + let (slice, elem) = slice.pop_back(); + assert(slice.len() == 3); + assert(elem == x); +} + +fn merge_slices_push_then_insert(x: Field, y: Field) -> [Field] { + let mut slice = &[0; 2]; + if x != y { + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice = slice.push_back(x); + } + + slice = slice.push_back(30); + + if x == 20 { + slice = slice.push_back(20); + slice = slice.push_back(15); + } + + slice = slice.insert(1, 50); + // Test that we can use slice insert the same as slice push back + slice = slice.insert(6, 100); + + slice +} + +fn merge_slices_remove_between_ifs(x: Field, y: Field) -> [Field] { + let mut slice = &[0; 2]; + if x != y { + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice = slice.push_back(x); + } + + let (mut slice, elem) = slice.remove(2); + assert(elem == y); + + if x == 20 { + slice = slice.push_back(20); + } + + slice = slice.push_back(15); + + if x != 20 { + slice = slice.push_back(50); + } + + slice +} +// Previously, we'd get a type error when trying to assign an array of a different size to +// an existing array variable. Now, we infer the variable must be a slice. +fn regression_2370() { + let mut slice = &[]; + slice = &[1, 2, 3]; +} + +fn regression_4418(x: Field) { + let mut crash: [u8; 32] = x.to_be_bytes(); + + 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/strings/Nargo.toml b/test_programs/execution_success/strings/Nargo.toml new file mode 100644 index 00000000000..76a9beb6909 --- /dev/null +++ b/test_programs/execution_success/strings/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "strings" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/strings/Prover.toml b/test_programs/execution_success/strings/Prover.toml new file mode 100644 index 00000000000..0d1bd92b5de --- /dev/null +++ b/test_programs/execution_success/strings/Prover.toml @@ -0,0 +1,4 @@ +message = "hello world" +y = 5 +hex_as_string = "0x41" +hex_as_field = "0x41" diff --git a/test_programs/execution_success/strings/src/main.nr b/test_programs/execution_success/strings/src/main.nr new file mode 100644 index 00000000000..c4fa0539745 --- /dev/null +++ b/test_programs/execution_success/strings/src/main.nr @@ -0,0 +1,84 @@ +// Test global string literals +global HELLO_WORLD: str<11> = "hello world"; + +fn main(message: pub str<11>, y: Field, hex_as_string: str<4>, hex_as_field: Field) { + let mut bad_message = "hello world"; + + assert(message == "hello world"); + assert(message == HELLO_WORLD); + let x = 10; + let z = x * 5; + std::println(10); + std::print(10); + + std::println(z); // x * 5 in println not yet supported + std::print(z); + std::println(x); + std::print(x); + + let array = [1, 2, 3, 5, 8]; + assert(y == 5); // Change to y != 5 to see how the later print statements are not called + std::println(array); + std::print(array); + + bad_message = "hell\0\"world"; + std::println(bad_message); + std::print(bad_message); + assert(message != bad_message); + + let hash = std::hash::pedersen_commitment([x]); + std::println(hash); + std::print(hash); + + assert(hex_as_string == "0x41"); + // assert(hex_as_string != 0x41); This will fail with a type mismatch between str[4] and Field + assert(hex_as_field == 0x41); + + // Single digit & odd length hex literals are valid + assert(hex_as_field == 0x041); + assert(hex_as_field != 0x1); +} + +#[test] +fn test_prints_strings() { + let message = "hello world!"; + + std::println(message); + std::println("goodbye world"); + + std::print(message); + std::print("\n"); + std::print("goodbye world\n"); +} + +#[test] +fn test_prints_array() { + let array = [1, 2, 3, 5, 8]; + + let s = Test { a: 1, b: 2, c: [3, 4] }; + std::println(s); + + std::println(array); + + let hash = std::hash::pedersen_commitment(array); + std::println(hash); +} + +fn failed_constraint(hex_as_field: Field) { + // When this method is called from a test method or with constant values + // a `Failed constraint` compile error will be caught before this `println` + // is executed as the input will be a constant. + std::println(hex_as_field); + assert(hex_as_field != 0x41); +} + +#[test] +fn test_failed_constraint() { + failed_constraint(0x41); +} + +struct Test { + a: Field, + b: Field, + c: [Field; 2], +} diff --git a/test_programs/execution_success/struct/Nargo.toml b/test_programs/execution_success/struct/Nargo.toml new file mode 100644 index 00000000000..6622edd0653 --- /dev/null +++ b/test_programs/execution_success/struct/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "struct" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/struct/Prover.toml b/test_programs/execution_success/struct/Prover.toml new file mode 100644 index 00000000000..7d59cc81807 --- /dev/null +++ b/test_programs/execution_success/struct/Prover.toml @@ -0,0 +1,2 @@ +x = "0" +y = "1" \ No newline at end of file diff --git a/test_programs/execution_success/struct/src/main.nr b/test_programs/execution_success/struct/src/main.nr new file mode 100644 index 00000000000..e4611b90b7d --- /dev/null +++ b/test_programs/execution_success/struct/src/main.nr @@ -0,0 +1,75 @@ +struct Foo { + bar: Field, + array: [Field; 2], +} + +struct Pair { + first: Foo, + second: Field, +} + +impl Foo { + fn default(x: Field, y: Field) -> Self { + Self { bar: 0, array: [x, y] } + } +} + +impl Pair { + fn foo(p: Self) -> Foo { + p.first + } + + fn bar(self) -> Field { + self.foo().bar + } +} + +struct Nested { + a: Field, + b: Field, +} +struct MyStruct { + my_bool: bool, + my_int: u32, + my_nest: Nested, +} +fn test_struct_in_tuple(a_bool: bool, x: Field, y: Field) -> (MyStruct, bool) { + let my_struct = MyStruct { my_bool: a_bool, my_int: 5, my_nest: Nested { a: x, b: y } }; + (my_struct, a_bool) +} + +struct Animal { + legs: Field, + eyes: u8, +} + +fn get_dog() -> Animal { + let dog = Animal { legs: 4, eyes: 2 }; + dog +} + +struct Unit; + +fn main(x: Field, y: Field) { + let unit = Unit {}; + + let first = Foo::default(x, y); + let p = Pair { first, second: 1 }; + + assert(p.bar() == x); + assert(p.second == y); + assert(p.first.array[0] != p.first.array[1]); + // Nested structs + let (struct_from_tuple, a_bool) = test_struct_in_tuple(true, x, y); + assert(struct_from_tuple.my_bool == true); + assert(a_bool == true); + assert(struct_from_tuple.my_int == 5); + assert(struct_from_tuple.my_nest.a == 0); + // Regression test for issue #670 + let Animal { legs, eyes } = get_dog(); + let six = legs + eyes as Field; + + assert(six == 6); + + let Animal { legs: _, eyes: _ } = get_dog(); +} diff --git a/test_programs/execution_success/struct_array_inputs/Nargo.toml b/test_programs/execution_success/struct_array_inputs/Nargo.toml new file mode 100644 index 00000000000..40160fb397f --- /dev/null +++ b/test_programs/execution_success/struct_array_inputs/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "struct_array_inputs" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/struct_array_inputs/Prover.toml b/test_programs/execution_success/struct_array_inputs/Prover.toml new file mode 100644 index 00000000000..c2212c1a9c9 --- /dev/null +++ b/test_programs/execution_success/struct_array_inputs/Prover.toml @@ -0,0 +1,11 @@ +[[foos]] +bar = 0 +baz = 0 + +[[foos]] +bar = 0 +baz = 0 + +[[foos]] +bar = 1 +baz = 2 diff --git a/test_programs/execution_success/struct_array_inputs/src/main.nr b/test_programs/execution_success/struct_array_inputs/src/main.nr new file mode 100644 index 00000000000..4a367558671 --- /dev/null +++ b/test_programs/execution_success/struct_array_inputs/src/main.nr @@ -0,0 +1,8 @@ +struct Foo { + bar: Field, + baz: Field, +} + +fn main(foos: [Foo; 3]) -> pub Field { + foos[2].bar + foos[2].baz +} diff --git a/test_programs/execution_success/struct_fields_ordering/Nargo.toml b/test_programs/execution_success/struct_fields_ordering/Nargo.toml new file mode 100644 index 00000000000..767f51acda3 --- /dev/null +++ b/test_programs/execution_success/struct_fields_ordering/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "struct_fields_ordering" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/struct_fields_ordering/Prover.toml b/test_programs/execution_success/struct_fields_ordering/Prover.toml new file mode 100644 index 00000000000..70640bba4cc --- /dev/null +++ b/test_programs/execution_success/struct_fields_ordering/Prover.toml @@ -0,0 +1,3 @@ +[y] +foo = "5" +bar = "7" diff --git a/test_programs/execution_success/struct_fields_ordering/src/main.nr b/test_programs/execution_success/struct_fields_ordering/src/main.nr new file mode 100644 index 00000000000..1a2e2d462e2 --- /dev/null +++ b/test_programs/execution_success/struct_fields_ordering/src/main.nr @@ -0,0 +1,12 @@ +// Note that fields are not in alphabetical order. +// We want to check that this ordering is maintained +struct myStruct { + foo: u32, + bar: Field, +} + +fn main(y: pub myStruct) { + assert(y.foo == 5); + assert(y.bar == 7); +} + diff --git a/test_programs/execution_success/struct_inputs/Nargo.toml b/test_programs/execution_success/struct_inputs/Nargo.toml new file mode 100644 index 00000000000..7dd6f78b750 --- /dev/null +++ b/test_programs/execution_success/struct_inputs/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "struct_inputs" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/struct_inputs/Prover.toml b/test_programs/execution_success/struct_inputs/Prover.toml new file mode 100644 index 00000000000..339da5b1a00 --- /dev/null +++ b/test_programs/execution_success/struct_inputs/Prover.toml @@ -0,0 +1,19 @@ +x = "5" + +[y] +foo = "5" +bar = "10" +message = "hello" + +[z] +val = "1" +array = [0, 1] +message = "helld" + +[a] +baz = 0 + +[a.bar_struct] +val = "1" +array = [0, 1] +message = "hello" diff --git a/test_programs/execution_success/struct_inputs/src/foo.nr b/test_programs/execution_success/struct_inputs/src/foo.nr new file mode 100644 index 00000000000..ea3a6bbe25f --- /dev/null +++ b/test_programs/execution_success/struct_inputs/src/foo.nr @@ -0,0 +1,6 @@ +mod bar; + +struct fooStruct { + bar_struct: bar::barStruct, + baz: Field, +} diff --git a/test_programs/execution_success/struct_inputs/src/foo/bar.nr b/test_programs/execution_success/struct_inputs/src/foo/bar.nr new file mode 100644 index 00000000000..7a79528f8ab --- /dev/null +++ b/test_programs/execution_success/struct_inputs/src/foo/bar.nr @@ -0,0 +1,7 @@ +global N: Field = 2; + +struct barStruct { + val: Field, + array: [Field; 2], + message: str<5>, +} diff --git a/test_programs/execution_success/struct_inputs/src/main.nr b/test_programs/execution_success/struct_inputs/src/main.nr new file mode 100644 index 00000000000..5b03483cbaf --- /dev/null +++ b/test_programs/execution_success/struct_inputs/src/main.nr @@ -0,0 +1,34 @@ +mod foo; + +struct myStruct { + foo: u32, + bar: Field, + message: str<5>, +} + +fn main(x: Field, y: pub myStruct, z: pub foo::bar::barStruct, a: pub foo::fooStruct) -> pub Field { + let struct_from_bar = foo::bar::barStruct { val: 1, array: [0, 1], message: "hello" }; + + check_inner_struct(a, z); + + for i in 0..struct_from_bar.array.len() { + assert(struct_from_bar.array[i] == z.array[i]); + } + assert(z.val == struct_from_bar.val); + + assert((struct_from_bar.val * x) == x); + + assert(x != y.bar); + + assert(y.message == "hello"); + assert(a.bar_struct.message == struct_from_bar.message); + + a.bar_struct.array[1] +} + +fn check_inner_struct(a: foo::fooStruct, z: foo::bar::barStruct) { + assert(a.bar_struct.val == z.val); + for i in 0..a.bar_struct.array.len() { + assert(a.bar_struct.array[i] == z.array[i]); + } +} diff --git a/test_programs/execution_success/submodules/Nargo.toml b/test_programs/execution_success/submodules/Nargo.toml new file mode 100644 index 00000000000..082afdf3f10 --- /dev/null +++ b/test_programs/execution_success/submodules/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "submodules" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/submodules/Prover.toml b/test_programs/execution_success/submodules/Prover.toml new file mode 100644 index 00000000000..b6626a67e19 --- /dev/null +++ b/test_programs/execution_success/submodules/Prover.toml @@ -0,0 +1,2 @@ +x = 1 +y = 0 diff --git a/test_programs/execution_success/submodules/src/main.nr b/test_programs/execution_success/submodules/src/main.nr new file mode 100644 index 00000000000..f937af74627 --- /dev/null +++ b/test_programs/execution_success/submodules/src/main.nr @@ -0,0 +1,15 @@ +use my_submodule::my_helper; + +fn main(x: u1, y: u1) { + my_helper(); + my_submodule::my_bool_or(x, y); +} + +mod my_submodule { + pub fn my_bool_or(x: u1, y: u1) { + assert(x | y == 1); + } + + pub fn my_helper() {} +} + diff --git a/test_programs/execution_success/to_be_bytes/Nargo.toml b/test_programs/execution_success/to_be_bytes/Nargo.toml new file mode 100644 index 00000000000..e9d2e30b4c4 --- /dev/null +++ b/test_programs/execution_success/to_be_bytes/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "to_be_bytes" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/to_be_bytes/Prover.toml b/test_programs/execution_success/to_be_bytes/Prover.toml new file mode 100644 index 00000000000..07fe857ac7c --- /dev/null +++ b/test_programs/execution_success/to_be_bytes/Prover.toml @@ -0,0 +1 @@ +x = "2040124" diff --git a/test_programs/execution_success/to_be_bytes/src/main.nr b/test_programs/execution_success/to_be_bytes/src/main.nr new file mode 100644 index 00000000000..062f9f763d5 --- /dev/null +++ b/test_programs/execution_success/to_be_bytes/src/main.nr @@ -0,0 +1,13 @@ +fn main(x: Field) -> pub [u8; 31] { + // The result of this byte array will be big-endian + let byte_array: [u8; 31] = x.to_be_bytes(); + let mut bytes = [0; 31]; + for i in 0..31 { + bytes[i] = byte_array[i]; + } + if (bytes[30] != 60) | (bytes[29] != 33) | (bytes[28] != 31) { + assert(false); + } + assert(Field::from_be_bytes::<31>(bytes) == x); + bytes +} 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/to_bits/src/main.nr b/test_programs/execution_success/to_bits/src/main.nr new file mode 100644 index 00000000000..dc2ff4be394 --- /dev/null +++ b/test_programs/execution_success/to_bits/src/main.nr @@ -0,0 +1,21 @@ +fn main() { + let field = 1000; + let be_bits: [u1; 16] = field.to_be_bits(); + let le_bits: [u1; 16] = field.to_le_bits(); + + for i in 0..16 { + let x = be_bits[i]; + let y = le_bits[15 - i]; + assert(x == y); + } + + let x = 3; + let be_bits_x: [u1; 4] = x.to_be_bits(); + let le_bits_x: [u1; 4] = x.to_le_bits(); + + for i in 0..4 { + let be_bit = be_bits_x[i]; + let le_bit = le_bits_x[3 - i]; + assert(be_bit == le_bit); + } +} diff --git a/test_programs/execution_success/to_bytes_consistent/Nargo.toml b/test_programs/execution_success/to_bytes_consistent/Nargo.toml new file mode 100644 index 00000000000..1e117b83883 --- /dev/null +++ b/test_programs/execution_success/to_bytes_consistent/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "to_bytes_consistent" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/to_bytes_consistent/Prover.toml b/test_programs/execution_success/to_bytes_consistent/Prover.toml new file mode 100644 index 00000000000..07fe857ac7c --- /dev/null +++ b/test_programs/execution_success/to_bytes_consistent/Prover.toml @@ -0,0 +1 @@ +x = "2040124" diff --git a/test_programs/execution_success/to_bytes_consistent/src/main.nr b/test_programs/execution_success/to_bytes_consistent/src/main.nr new file mode 100644 index 00000000000..171ac9dfbc0 --- /dev/null +++ b/test_programs/execution_success/to_bytes_consistent/src/main.nr @@ -0,0 +1,13 @@ +// This test aims to check that we have consistent behavior +// between a `to_be_bytes` call (which is radix decomposition under the hood) +// with constant inputs or with witness inputs. +// x = 2040124 +fn main(x: Field) { + let byte_array: [u8; 31] = x.to_be_bytes(); + let x_as_constant = 2040124; + let constant_byte_array: [u8; 31] = x_as_constant.to_be_bytes(); + assert(constant_byte_array.len() == byte_array.len()); + for i in 0..constant_byte_array.len() { + assert(constant_byte_array[i] == byte_array[i]); + } +} diff --git a/test_programs/execution_success/to_bytes_integration/Nargo.toml b/test_programs/execution_success/to_bytes_integration/Nargo.toml new file mode 100644 index 00000000000..c89c32eb06c --- /dev/null +++ b/test_programs/execution_success/to_bytes_integration/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "to_bytes_integration" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/to_bytes_integration/Prover.toml b/test_programs/execution_success/to_bytes_integration/Prover.toml new file mode 100644 index 00000000000..bc4693e434a --- /dev/null +++ b/test_programs/execution_success/to_bytes_integration/Prover.toml @@ -0,0 +1,2 @@ +x = "2040124" +a = "0x2000000000000000000000000000000000000000000000000000000000000000" diff --git a/test_programs/execution_success/to_bytes_integration/src/main.nr b/test_programs/execution_success/to_bytes_integration/src/main.nr new file mode 100644 index 00000000000..21245378971 --- /dev/null +++ b/test_programs/execution_success/to_bytes_integration/src/main.nr @@ -0,0 +1,23 @@ +fn main(x: Field, a: Field) { + let y: Field = 2040124; + let be_byte_array: [u8; 31] = y.to_be_bytes(); + let le_byte_array: [u8; 31] = x.to_le_bytes(); + + 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: [u8; 32] = z.to_le_bytes(); + 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: [u1; 254] = z.to_le_bits(); + assert(z_bits[0] == 0); + assert(p_bits[100] == z_bits[100]); + + let _: [u1; 254] = a.to_le_bits(); +} diff --git a/test_programs/execution_success/to_le_bytes/Nargo.toml b/test_programs/execution_success/to_le_bytes/Nargo.toml new file mode 100644 index 00000000000..3d02c3510fd --- /dev/null +++ b/test_programs/execution_success/to_le_bytes/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "to_le_bytes" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/to_le_bytes/Prover.toml b/test_programs/execution_success/to_le_bytes/Prover.toml new file mode 100644 index 00000000000..bf58776d557 --- /dev/null +++ b/test_programs/execution_success/to_le_bytes/Prover.toml @@ -0,0 +1,2 @@ +x = "2040124" +cond = false \ No newline at end of file diff --git a/test_programs/execution_success/to_le_bytes/src/main.nr b/test_programs/execution_success/to_le_bytes/src/main.nr new file mode 100644 index 00000000000..867551b6dbd --- /dev/null +++ b/test_programs/execution_success/to_le_bytes/src/main.nr @@ -0,0 +1,13 @@ +fn main(x: Field, cond: bool) -> pub [u8; 31] { + // The result of this byte array will be little-endian + let byte_array: [u8; 31] = x.to_le_bytes(); + assert(byte_array.len() == 31); + assert(Field::from_le_bytes::<31>(byte_array) == x); + if cond { + // We've set x = "2040124" so we shouldn't be able to represent this as a single byte. + let bad_byte_array: [u8; 1] = x.to_le_bytes(); + assert_eq(bad_byte_array.len(), 1); + } + + byte_array +} diff --git a/test_programs/execution_success/trait_as_return_type/Nargo.toml b/test_programs/execution_success/trait_as_return_type/Nargo.toml new file mode 100644 index 00000000000..afd89f0c3a1 --- /dev/null +++ b/test_programs/execution_success/trait_as_return_type/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "trait_as_return_type" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/trait_as_return_type/Prover.toml b/test_programs/execution_success/trait_as_return_type/Prover.toml new file mode 100644 index 00000000000..a0cd58138b6 --- /dev/null +++ b/test_programs/execution_success/trait_as_return_type/Prover.toml @@ -0,0 +1 @@ +x = "5" \ No newline at end of file diff --git a/test_programs/execution_success/trait_as_return_type/src/main.nr b/test_programs/execution_success/trait_as_return_type/src/main.nr new file mode 100644 index 00000000000..905f7f5d8b3 --- /dev/null +++ b/test_programs/execution_success/trait_as_return_type/src/main.nr @@ -0,0 +1,51 @@ +trait SomeTrait { + fn magic_number(self) -> Field; +} + +struct A {} +struct B {} +struct C { + x: Field, +} + +impl SomeTrait for A { + fn magic_number(self) -> Field { + 2 + } +} + +impl SomeTrait for B { + fn magic_number(self) -> Field { + 4 + } +} + +impl SomeTrait for C { + fn magic_number(self) -> Field { + self.x + } +} + +fn factory_a() -> impl SomeTrait { + A {} +} + +fn factory_b() -> impl SomeTrait { + B {} +} + +fn factory_c(x: Field) -> impl SomeTrait { + C { x } +} +// x = 15 +fn main(x: u32) { + let a = factory_a(); + let b = B {}; + let b2 = factory_b(); + assert(a.magic_number() == 2); + assert(b.magic_number() == 4); + assert(b2.magic_number() == 4); + let c = factory_c(10); + assert(c.magic_number() == 10); + assert(factory_c(13).magic_number() == 13); +} diff --git a/test_programs/execution_success/trait_impl_base_type/Nargo.toml b/test_programs/execution_success/trait_impl_base_type/Nargo.toml new file mode 100644 index 00000000000..845498737c1 --- /dev/null +++ b/test_programs/execution_success/trait_impl_base_type/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "trait_impl_base_type" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/trait_impl_base_type/Prover.toml b/test_programs/execution_success/trait_impl_base_type/Prover.toml new file mode 100644 index 00000000000..a0cd58138b6 --- /dev/null +++ b/test_programs/execution_success/trait_impl_base_type/Prover.toml @@ -0,0 +1 @@ +x = "5" \ No newline at end of file diff --git a/test_programs/execution_success/trait_impl_base_type/src/main.nr b/test_programs/execution_success/trait_impl_base_type/src/main.nr new file mode 100644 index 00000000000..d12da11bc54 --- /dev/null +++ b/test_programs/execution_success/trait_impl_base_type/src/main.nr @@ -0,0 +1,115 @@ +trait Fieldable { + fn to_field(self) -> Field; +} + +impl Fieldable for u32 { + fn to_field(self) -> Field { + let res = self as Field; + res * 3 + } +} + +impl Fieldable for [u32; 3] { + fn to_field(self) -> Field { + let res = self[0] + self[1] + self[2]; + res as Field + } +} + +impl Fieldable for bool { + fn to_field(self) -> Field { + if self { + 14 + } else { + 3 + } + } +} + +impl Fieldable for (u32, bool) { + fn to_field(self) -> Field { + if self.1 { + self.0 as Field + } else { + 32 + } + } +} + +impl Fieldable for Field { + fn to_field(self) -> Field { + self + } +} + +impl Fieldable for str<6> { + fn to_field(self) -> Field { + 6 + } +} + +impl Fieldable for () { + fn to_field(self) -> Field { + 0 + } +} + +type Point2D = [Field; 2]; +type Point2DAlias = Point2D; + +impl Fieldable for Point2DAlias { + fn to_field(self) -> Field { + self[0] + self[1] + } +} + +impl Fieldable for fmtstr<14, (Field, Field)> { + fn to_field(self) -> Field { + 52 + } +} + +impl Fieldable for fn(u32) -> u32 { + fn to_field(self) -> Field { + self(10) as Field + } +} + +fn some_func(x: u32) -> u32 { + x * 2 - 3 +} + +impl Fieldable for u64 { + fn to_field(self) -> Field { + 66 as Field + } +} +// x = 15 +fn main(x: u32) { + assert(x.to_field() == 15); + let arr: [u32; 3] = [3, 5, 8]; + assert(arr.to_field() == 16); + let b_true = 2 == 2; + assert(b_true.to_field() == 14); + let b_false = 2 == 3; + assert(b_false.to_field() == 3); + let f = 13 as Field; + assert(f.to_field() == 13); + let k_true = (12 as u32, true); + assert(k_true.to_field() == 12); + let k_false = (11 as u32, false); + assert(k_false.to_field() == 32); + let m = "String"; + assert(m.to_field() == 6); + let unit = (); + assert(unit.to_field() == 0); + let point: Point2DAlias = [2, 3]; + assert(point.to_field() == 5); + let i: Field = 2; + let j: Field = 6; + assert(f"i: {i}, j: {j}".to_field() == 52); + assert(some_func.to_field() == 17); + + let mut y = 0 as u64; + assert(y.to_field() == 66); +} diff --git a/test_programs/execution_success/traits_in_crates_1/Nargo.toml b/test_programs/execution_success/traits_in_crates_1/Nargo.toml new file mode 100644 index 00000000000..555c3b38b98 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_1/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "traits_in_crates_1" +type = "bin" +authors = [""] +[dependencies] +crate1 = { path = "crate1" } +crate2 = { path = "crate2" } diff --git a/test_programs/execution_success/traits_in_crates_1/Prover.toml b/test_programs/execution_success/traits_in_crates_1/Prover.toml new file mode 100644 index 00000000000..c2005d59807 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_1/Prover.toml @@ -0,0 +1,2 @@ +x = 1 +y = 11 diff --git a/test_programs/execution_success/traits_in_crates_1/crate1/Nargo.toml b/test_programs/execution_success/traits_in_crates_1/crate1/Nargo.toml new file mode 100644 index 00000000000..f49603ba203 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_1/crate1/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "crate1" +type = "lib" +authors = [""] +[dependencies] +crate2 = { path = "../crate2" } diff --git a/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr b/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr new file mode 100644 index 00000000000..e36a263093a --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr @@ -0,0 +1,9 @@ +trait MyTrait { + fn Add10(&mut self); +} + +impl MyTrait for crate2::MyStruct { + fn Add10(&mut self) { + self.Q += 10; + } +} diff --git a/test_programs/execution_success/traits_in_crates_1/crate2/Nargo.toml b/test_programs/execution_success/traits_in_crates_1/crate2/Nargo.toml new file mode 100644 index 00000000000..c86c5edf51a --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_1/crate2/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "crate2" +type = "lib" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/traits_in_crates_1/crate2/src/lib.nr b/test_programs/execution_success/traits_in_crates_1/crate2/src/lib.nr new file mode 100644 index 00000000000..c59bf0387c1 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_1/crate2/src/lib.nr @@ -0,0 +1,3 @@ +struct MyStruct { + Q: Field, +} diff --git a/test_programs/execution_success/traits_in_crates_1/src/main.nr b/test_programs/execution_success/traits_in_crates_1/src/main.nr new file mode 100644 index 00000000000..2afec29ee1f --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_1/src/main.nr @@ -0,0 +1,5 @@ +fn main(x: Field, y: pub Field) { + let mut V = crate2::MyStruct { Q: x }; + V.Add10(); + assert(V.Q == y); +} diff --git a/test_programs/execution_success/traits_in_crates_2/Nargo.toml b/test_programs/execution_success/traits_in_crates_2/Nargo.toml new file mode 100644 index 00000000000..11a86a08402 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_2/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "traits_in_crates_2" +type = "bin" +authors = [""] +[dependencies] +crate1 = { path = "crate1" } +crate2 = { path = "crate2" } diff --git a/test_programs/execution_success/traits_in_crates_2/Prover.toml b/test_programs/execution_success/traits_in_crates_2/Prover.toml new file mode 100644 index 00000000000..c2005d59807 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_2/Prover.toml @@ -0,0 +1,2 @@ +x = 1 +y = 11 diff --git a/test_programs/execution_success/traits_in_crates_2/crate1/Nargo.toml b/test_programs/execution_success/traits_in_crates_2/crate1/Nargo.toml new file mode 100644 index 00000000000..de1eddf2cf0 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_2/crate1/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "crate1" +type = "lib" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/traits_in_crates_2/crate1/src/lib.nr b/test_programs/execution_success/traits_in_crates_2/crate1/src/lib.nr new file mode 100644 index 00000000000..59a28a50c79 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_2/crate1/src/lib.nr @@ -0,0 +1,3 @@ +trait MyTrait { + fn Add10(&mut self); +} diff --git a/test_programs/execution_success/traits_in_crates_2/crate2/Nargo.toml b/test_programs/execution_success/traits_in_crates_2/crate2/Nargo.toml new file mode 100644 index 00000000000..885d41f0a27 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_2/crate2/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "crate2" +type = "lib" +authors = [""] +[dependencies] +crate1 = { path = "../crate1" } diff --git a/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr b/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr new file mode 100644 index 00000000000..fe6a94a4a95 --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr @@ -0,0 +1,9 @@ +struct MyStruct { + Q: Field, +} + +impl crate1::MyTrait for MyStruct { + fn Add10(&mut self) { + self.Q += 10; + } +} diff --git a/test_programs/execution_success/traits_in_crates_2/src/main.nr b/test_programs/execution_success/traits_in_crates_2/src/main.nr new file mode 100644 index 00000000000..2afec29ee1f --- /dev/null +++ b/test_programs/execution_success/traits_in_crates_2/src/main.nr @@ -0,0 +1,5 @@ +fn main(x: Field, y: pub Field) { + let mut V = crate2::MyStruct { Q: x }; + V.Add10(); + assert(V.Q == y); +} diff --git a/test_programs/execution_success/tuple_inputs/Nargo.toml b/test_programs/execution_success/tuple_inputs/Nargo.toml new file mode 100644 index 00000000000..f4af6cfe6e3 --- /dev/null +++ b/test_programs/execution_success/tuple_inputs/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "tuple_inputs" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/tuple_inputs/Prover.toml b/test_programs/execution_success/tuple_inputs/Prover.toml new file mode 100644 index 00000000000..43d62a7a15b --- /dev/null +++ b/test_programs/execution_success/tuple_inputs/Prover.toml @@ -0,0 +1,12 @@ +pair = [1, 0] +x = [[0, 1, 2], [3, 4, 5]] + +[[struct_pair]] +a = "1" +b = ["2", "3", "20"] + +[struct_pair.bar] +inner = ["100", "101", "102"] + +[[struct_pair]] +inner = ["103", "104", "105"] diff --git a/test_programs/execution_success/tuple_inputs/src/main.nr b/test_programs/execution_success/tuple_inputs/src/main.nr new file mode 100644 index 00000000000..38fec58f14f --- /dev/null +++ b/test_programs/execution_success/tuple_inputs/src/main.nr @@ -0,0 +1,35 @@ +struct Bar { + inner: [Field; 3], +} + +struct Foo { + a: Field, + b: [Field; 3], + bar: Bar, +} + +fn main(pair: (Field, Field), x: [(u8, u8, u8); 2], struct_pair: (Foo, Bar)) -> pub (Field, u8) { + let mut start_val = 0; + for i in 0..2 { + assert(x[i].0 == start_val); + assert(x[i].1 == start_val + 1); + assert(x[i].2 == start_val + 2); + start_val += 3; + } + + assert(struct_pair.0.a == 1); + assert(struct_pair.0.b == [2, 3, 20]); + assert(struct_pair.0.bar.inner == [100, 101, 102]); + assert(struct_pair.1.inner == [103, 104, 105]); + + let (u, v) = if pair.0 as u32 < 1 { + (pair.0, pair.0 + 1) + } else { + (pair.0 + 1, pair.0) + }; + + assert(u == pair.0 + 1); + assert(v == pair.0); + + (u, v as u8) +} diff --git a/test_programs/execution_success/tuples/Nargo.toml b/test_programs/execution_success/tuples/Nargo.toml new file mode 100644 index 00000000000..f6ed9f1e649 --- /dev/null +++ b/test_programs/execution_success/tuples/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "tuples" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/tuples/Prover.toml b/test_programs/execution_success/tuples/Prover.toml new file mode 100644 index 00000000000..a0397e89477 --- /dev/null +++ b/test_programs/execution_success/tuples/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "0" diff --git a/test_programs/execution_success/tuples/src/main.nr b/test_programs/execution_success/tuples/src/main.nr new file mode 100644 index 00000000000..5526fcad422 --- /dev/null +++ b/test_programs/execution_success/tuples/src/main.nr @@ -0,0 +1,22 @@ +fn main(x: Field, y: Field) { + let pair = (x, y); + assert(pair.0 == 1); + assert(pair.1 == 0); + + let (a, b) = if true { (0, 1) } else { (2, 3) }; + assert(a == 0); + assert(b == 1); + + let (u, v) = if x as u32 < 1 { (x, x + 1) } else { (x + 1, x) }; + assert(u == x + 1); + assert(v == x); + // Test mutating tuples + let mut mutable = ((0, 0), 1, 2, 3); + mutable.0 = (x, y); + mutable.2 = 7; + assert(mutable.0.0 == 1); + assert(mutable.0.1 == 0); + assert(mutable.1 == 1); + assert(mutable.2 == 7); + assert(mutable.3 == 3); +} diff --git a/test_programs/execution_success/type_aliases/Nargo.toml b/test_programs/execution_success/type_aliases/Nargo.toml new file mode 100644 index 00000000000..a12df601a91 --- /dev/null +++ b/test_programs/execution_success/type_aliases/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "type_aliases" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/type_aliases/Prover.toml b/test_programs/execution_success/type_aliases/Prover.toml new file mode 100644 index 00000000000..771df41899d --- /dev/null +++ b/test_programs/execution_success/type_aliases/Prover.toml @@ -0,0 +1 @@ +x = [2, 3] diff --git a/test_programs/execution_success/type_aliases/src/main.nr b/test_programs/execution_success/type_aliases/src/main.nr new file mode 100644 index 00000000000..ee62b0b7260 --- /dev/null +++ b/test_programs/execution_success/type_aliases/src/main.nr @@ -0,0 +1,33 @@ +type Foo = [T; 2]; + +type Bar = Field; + +type One = (A, B); +type Two = One; +type Three = Two; + +struct MyStruct { + foo: Bar, +} + +fn main(x: [Field; 2]) { + let a: Foo = [1, 2]; + assert(a[0] != x[0]); + + let b: Bar = 2; + assert(x[0] == b); + + let c: u8 = 1; + let d: u32 = 2; + let e: Three = (c, d); + assert(e.0 == 1); + + let s = MyStruct { foo: 10 }; + assert(s.foo == 10); + + let _regression2502: Regression2502Alias = Regression2502 {}; +} +// An ICE was occurring if a type alias referred to a struct before it was initialized +// during name resolution. The fix was to initialize structs during def collection instead. +type Regression2502Alias = Regression2502; +struct Regression2502 {} diff --git a/test_programs/execution_success/u128/Nargo.toml b/test_programs/execution_success/u128/Nargo.toml new file mode 100644 index 00000000000..c1dcd84db04 --- /dev/null +++ b/test_programs/execution_success/u128/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "u128" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/u128/Prover.toml b/test_programs/execution_success/u128/Prover.toml new file mode 100644 index 00000000000..961db9825a7 --- /dev/null +++ b/test_programs/execution_success/u128/Prover.toml @@ -0,0 +1,7 @@ +x = "3" +y = "4" +z = "7" +hexa ="0x1f03a" +[big_int] +lo = 1 +hi = 2 \ No newline at end of file diff --git a/test_programs/execution_success/u128/src/main.nr b/test_programs/execution_success/u128/src/main.nr new file mode 100644 index 00000000000..4ea93437814 --- /dev/null +++ b/test_programs/execution_success/u128/src/main.nr @@ -0,0 +1,42 @@ +fn main(mut x: u32, y: u32, z: u32, big_int: U128, hexa: str<7>) { + let a = U128::from_u64s_le(x as u64, x as u64); + let b = U128::from_u64s_le(y as u64, x as u64); + let c = a + b; + assert(c.lo == z as Field); + assert(c.hi == 2 * x as Field); + assert(U128::from_hex(hexa).lo == 0x1f03a); + let t1 = U128::from_hex("0x9d9c7a87771f03a23783f9d9c7a8777"); + let t2 = U128::from_hex("0x45a26c708BFCF39041"); + let t = t1 + t2; + assert(t.lo == 0xc5e4b029996e17b8); + assert(t.hi == 0x09d9c7a87771f07f); + let t3 = U128::from_le_bytes(t.to_le_bytes()); + assert(t == t3); + + let t4 = t - t2; + assert(t4 == t1); + + let t5 = U128::from_u64s_le(0, 1); + let t6 = U128::from_u64s_le(1, 0); + assert((t5 - t6).hi == 0); + + assert( + (U128::from_hex("0x71f03a23783f9d9c7a8777") * U128::from_hex("0x8BFCF39041")).hi + == U128::from_hex("0x3e4e0471b873470e247c824e61445537").hi, + ); + let q = U128::from_hex("0x3e4e0471b873470e247c824e61445537") / U128::from_hex("0x8BFCF39041"); + assert(q == U128::from_hex("0x71f03a23783f9d9c7a8777")); + + assert(big_int.hi == 2); + + 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 << (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..d86ad348708 --- /dev/null +++ b/test_programs/execution_success/u16_support/src/main.nr @@ -0,0 +1,27 @@ +fn main(x: u16) { + test_u16(x); + /// Safety: testing context + 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/uhashmap/Nargo.toml b/test_programs/execution_success/uhashmap/Nargo.toml new file mode 100644 index 00000000000..0d898e53003 --- /dev/null +++ b/test_programs/execution_success/uhashmap/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "uhashmap" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/uhashmap/Prover.toml b/test_programs/execution_success/uhashmap/Prover.toml new file mode 100644 index 00000000000..84d4c0733e4 --- /dev/null +++ b/test_programs/execution_success/uhashmap/Prover.toml @@ -0,0 +1,26 @@ +# Input: 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/execution_success/uhashmap/src/main.nr b/test_programs/execution_success/uhashmap/src/main.nr new file mode 100644 index 00000000000..6163d5b954b --- /dev/null +++ b/test_programs/execution_success/uhashmap/src/main.nr @@ -0,0 +1,351 @@ +use std::collections::umap::UHashMap; +use std::hash::BuildHasherDefault; +use std::hash::poseidon2::Poseidon2Hasher; + +type K = Field; +type V = Field; + +// It is more convenient and readable to use structs as input. +struct Entry { + key: Field, + value: Field, +} + +global HASHMAP_LEN: u32 = 6; + +global FIELD_CMP: fn(Field, Field) -> bool = |a: Field, b: Field| a.lt(b); + +global K_CMP: fn(Field, Field) -> bool = FIELD_CMP; +global V_CMP: fn(Field, Field) -> bool = FIELD_CMP; +global KV_CMP: fn((K, V), (K, V)) -> bool = |a: (K, V), b: (K, V)| a.0.lt(b.0); + +global ALLOCATE_HASHMAP: fn() -> UHashMap> = + || -> UHashMap> UHashMap::default(); + +unconstrained fn main(input: [Entry; HASHMAP_LEN]) { + test_sequential(input[0].key, input[0].value); + test_multiple_equal_insert(input[1].key, input[1].value); + test_value_override(input[2].key, input[2].value, input[3].value); + test_insert_and_methods(input); + test_hashmaps_equality(input); + test_retain(); + test_iterators(); + test_mut_iterators(); + + doc_tests(); +} + +// Insert, get, remove. +unconstrained fn test_sequential(key: K, value: V) { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New UHashMap should be empty."); + + hashmap.insert(key, value); + assert(hashmap.len() == 1, "UHashMap after one insert should have a length of 1 element."); + + let got = hashmap.get(key); + assert(got.is_some(), "Got none value."); + let got = got.unwrap_unchecked(); + assert(value == got, f"Inserted {value} but got {got} for the same key."); + + hashmap.remove(key); + assert( + hashmap.is_empty(), + "UHashMap after one insert and corresponding removal should be empty.", + ); + let got = hashmap.get(key); + assert(got.is_none(), "Value has been removed, but is still available (not none)."); +} + +// Insert same pair several times. +unconstrained fn test_multiple_equal_insert(key: K, value: V) { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New UHashMap should be empty."); + + for _ in 0..HASHMAP_LEN { + hashmap.insert(key, value); + } + + let len = hashmap.len(); + assert(len == 1, f"UHashMap length must be 1, got {len}."); + + let got = hashmap.get(key); + assert(got.is_some(), "Got none value."); + let got = got.unwrap_unchecked(); + assert(value == got, f"Inserted {value} but got {got} for the same key."); +} + +// Override value for existing pair. +unconstrained fn test_value_override(key: K, value: V, new_value: V) { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New hashmap should be empty."); + + hashmap.insert(key, value); + hashmap.insert(key, new_value); + assert(hashmap.len() == 1, "UHashMap length is invalid."); + + let got = hashmap.get(key); + assert(got.is_some(), "Got none value."); + let got = got.unwrap_unchecked(); + assert(got == new_value, f"Expected {new_value}, but got {got}."); +} + +// Insert several distinct pairs and test auxiliary methods. +unconstrained fn test_insert_and_methods(input: [Entry; HASHMAP_LEN]) { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New UHashMap should be empty."); + + for entry in input { + println(f"Inserting {entry}"); + hashmap.insert(entry.key, entry.value); + } + + println(hashmap.len()); + assert(hashmap.len() == HASHMAP_LEN, "hashmap.len() does not match input length."); + + for entry in input { + let entry_key = entry.key; + assert(hashmap.contains_key(entry.key), f"Not found inserted key {entry_key}."); + } + + hashmap.clear(); + assert(hashmap.is_empty(), "UHashMap after clear() should be empty."); +} + +// Insert several pairs and test retaining. +unconstrained fn test_retain() { + let mut hashmap = ALLOCATE_HASHMAP(); + assert(hashmap.is_empty(), "New UHashMap should be empty."); + + let (key, value) = (5, 11); + hashmap.insert(key, value); + let (key, value) = (2, 13); + hashmap.insert(key, value); + let (key, value) = (11, 5); + hashmap.insert(key, value); + + let predicate = |key: K, value: V| -> bool { key * value == 55 }; + hashmap.retain(predicate); + + assert(hashmap.len() == 2, "UHashMap should have retained 2 elements."); + assert( + hashmap.get(2).is_none(), + "Pair should have been removed, since it does not match predicate.", + ); +} + +// Equality trait check. +unconstrained fn test_hashmaps_equality(input: [Entry; HASHMAP_LEN]) { + let mut hashmap_1 = ALLOCATE_HASHMAP(); + let mut hashmap_2 = ALLOCATE_HASHMAP(); + + for entry in input { + hashmap_1.insert(entry.key, entry.value); + hashmap_2.insert(entry.key, entry.value); + } + + assert(hashmap_1 == hashmap_2, "CtHashMaps should be equal."); + + hashmap_2.remove(input[0].key); + + assert(hashmap_1 != hashmap_2, "CtHashMaps should not be equal."); +} + +// Test entries, keys, values. +unconstrained fn test_iterators() { + let mut hashmap = ALLOCATE_HASHMAP(); + + hashmap.insert(2, 3); + hashmap.insert(5, 7); + hashmap.insert(11, 13); + + let keys: [K; 3] = hashmap.keys().as_array().sort_via(K_CMP); + let values: [V; 3] = hashmap.values().as_array().sort_via(V_CMP); + let entries: [(K, V); 3] = hashmap.entries().as_array().sort_via(KV_CMP); + + assert(keys == [2, 5, 11], "Got incorrect iteration of keys."); + assert(values == [3, 7, 13], "Got incorrect iteration of values."); + assert(entries == [(2, 3), (5, 7), (11, 13)], "Got incorrect iteration of entries."); +} + +// Test mutable iteration over keys, values and entries. +unconstrained fn test_mut_iterators() { + let mut hashmap = ALLOCATE_HASHMAP(); + + hashmap.insert(2, 3); + hashmap.insert(5, 7); + hashmap.insert(11, 13); + + let f = |k: K| -> K { k * 3 }; + hashmap.iter_keys_mut(f); + + let f = |v: V| -> V { v * 5 }; + hashmap.iter_values_mut(f); + + let keys: [K; 3] = hashmap.keys().as_array().sort_via(K_CMP); + let values: [V; 3] = hashmap.values().as_array().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."); + + let f = |k: K, v: V| -> (K, V) { (k * 2, v * 2) }; + hashmap.iter_mut(f); + + let entries: [(K, V); 3] = hashmap.entries().as_array().sort_via(KV_CMP); + + assert(entries == [(12, 30), (30, 70), (66, 130)], "Got incorrect iteration of entries."); +} + +// docs:start:type_alias +type MyMap = UHashMap>; +// docs:end:type_alias + +/// Tests examples from the stdlib cthashmap documentation +unconstrained fn doc_tests() { + // docs:start:default_example + let hashmap: UHashMap> = UHashMap::default(); + assert(hashmap.is_empty()); + // docs:end:default_example + // docs:start:with_hasher_example + let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: UHashMap> = + UHashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); + // docs:end:with_hasher_example + // docs:start:insert_example + let mut map: UHashMap> = UHashMap::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: UHashMap> = + UHashMap::default(); + assert(empty_map.len() == 0); + println(empty_map.capacity()); + // 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: UHashMap> = UHashMap::default(); + let mut map2: UHashMap> = UHashMap::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: UHashMap>) { + /// Safety: testing context + let x = unsafe { map.get(12) }; + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +// docs:end:get_example + +fn entries_examples(map: UHashMap>) { + // 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[i]; + println(f"{key} -> {value}"); + } + } + // docs:end:entries_example + // docs:start:keys_example + let keys = map.keys(); + + for key in keys { + /// Safety: testing context + let value = unsafe { map.get(key) }.unwrap_unchecked(); + println(f"{key} -> {value}"); + } + // docs:end:keys_example + // docs:start:values_example + let values = map.values(); + + for value in values { + println(f"Found value {value}"); + } + // docs:end:values_example +} + +unconstrained fn iter_examples( + mut map: UHashMap>, +) { + // 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/unary_operator_overloading/Nargo.toml b/test_programs/execution_success/unary_operator_overloading/Nargo.toml new file mode 100644 index 00000000000..ebc88faaaf4 --- /dev/null +++ b/test_programs/execution_success/unary_operator_overloading/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unary_operator_overloading" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] diff --git a/test_programs/execution_success/unary_operator_overloading/Prover.toml b/test_programs/execution_success/unary_operator_overloading/Prover.toml new file mode 100644 index 00000000000..b95c23a4d31 --- /dev/null +++ b/test_programs/execution_success/unary_operator_overloading/Prover.toml @@ -0,0 +1 @@ +x = 3 diff --git a/test_programs/execution_success/unary_operator_overloading/src/main.nr b/test_programs/execution_success/unary_operator_overloading/src/main.nr new file mode 100644 index 00000000000..bf931d8dafb --- /dev/null +++ b/test_programs/execution_success/unary_operator_overloading/src/main.nr @@ -0,0 +1,36 @@ +use std::ops::{Neg, Not}; + +// x = 3 +fn main(x: u32) { + let wx = Wrapper::new(x as i32); + let ex: i32 = 3; + + assert((-wx).inner == -ex); + assert((!wx).inner == !ex); + + // Check that it works with type variables (x's type isn't immediately known) + let x = 3; + assert(-3 == -x); +} + +struct Wrapper { + inner: i32, +} + +impl Wrapper { + fn new(inner: i32) -> Self { + Wrapper { inner } + } +} + +impl Neg for Wrapper { + fn neg(self) -> Wrapper { + Wrapper::new(-self.inner) + } +} + +impl Not for Wrapper { + fn not(self) -> Wrapper { + Wrapper::new(!self.inner) + } +} diff --git a/test_programs/execution_success/unsafe_range_constraint/Nargo.toml b/test_programs/execution_success/unsafe_range_constraint/Nargo.toml new file mode 100644 index 00000000000..8714d95ed54 --- /dev/null +++ b/test_programs/execution_success/unsafe_range_constraint/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unsafe_range_constraint" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/unsafe_range_constraint/Prover.toml b/test_programs/execution_success/unsafe_range_constraint/Prover.toml new file mode 100644 index 00000000000..07890234a19 --- /dev/null +++ b/test_programs/execution_success/unsafe_range_constraint/Prover.toml @@ -0,0 +1 @@ +x = "3" diff --git a/test_programs/execution_success/unsafe_range_constraint/src/main.nr b/test_programs/execution_success/unsafe_range_constraint/src/main.nr new file mode 100644 index 00000000000..ed846ec20b4 --- /dev/null +++ b/test_programs/execution_success/unsafe_range_constraint/src/main.nr @@ -0,0 +1,5 @@ +// Test that we can apply a range constraint to a field using +// a builtin. +fn main(x: Field) { + x.assert_max_bit_size::<48>(); +} diff --git a/test_programs/execution_success/verify_honk_proof/Nargo.toml b/test_programs/execution_success/verify_honk_proof/Nargo.toml new file mode 100644 index 00000000000..8fce1bf44b6 --- /dev/null +++ b/test_programs/execution_success/verify_honk_proof/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "verify_honk_proof" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/verify_honk_proof/Prover.toml b/test_programs/execution_success/verify_honk_proof/Prover.toml new file mode 100644 index 00000000000..45a84c26eb8 --- /dev/null +++ b/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -0,0 +1,4 @@ +key_hash = "0x0000000000000000000000000000000000000000000000000000000000000000" +proof = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf", "0x00000000000000000000000000000000000000000000000b75c020998797da78", "0x0000000000000000000000000000000000000000000000005a107acb64952eca", "0x000000000000000000000000000000000000000000000000000031e97a575e9d", "0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4", "0x00000000000000000000000000000000000000000000000c410db10a01750aeb", "0x00000000000000000000000000000000000000000000000d722669117f9758a4", "0x000000000000000000000000000000000000000000000000000178cbf4206471", "0x000000000000000000000000000000000000000000000000e91b8a11e7842c38", "0x000000000000000000000000000000000000000000000007fd51009034b3357f", "0x000000000000000000000000000000000000000000000009889939f81e9c7402", "0x0000000000000000000000000000000000000000000000000000f94656a2ca48", "0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f", "0x0000000000000000000000000000000000000000000000093fe27776f50224bd", "0x000000000000000000000000000000000000000000000004a0c80c0da527a081", "0x0000000000000000000000000000000000000000000000000001b52c2020d746", "0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632", "0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc", "0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62", "0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c", "0x000000000000000000000000000000b0804efd6573805f991458295f510a2004", "0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e", "0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47", "0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15", "0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd", "0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383", "0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4", "0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x0000000000000000000000000000006cf7dd96d7636fda5953191b1ad776d491", "0x00000000000000000000000000000000001633d881a08d136e834cb13a28fcc6", "0x00000000000000000000000000000001254956cff6908b069fca0e6cf1c47eb1", "0x000000000000000000000000000000000006f4d4dd3890e997e75e75886bf8f7", "0x000000000000000000000000000000f968b227a358a305607f3efc933823d288", "0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08", "0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f", "0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1", "0x00000000000000000000000000000052eebbd1f6f7554e837f60c44000ed14b6", "0x00000000000000000000000000000000001c1c045a3ec94b8801f2272cc0b3f4", "0x0000000000000000000000000000004d2ef74134578f6b431a9df071ffca4292", "0x0000000000000000000000000000000000291326ade7aa6f0dfc8900eab5580b", "0x0000000000000000000000000000002433eec6418a6dba820c9527e2581fc8bc", "0x00000000000000000000000000000000000e88b7daad19af2ac2f9bdf9e50ee2", "0x000000000000000000000000000000dcfce2c427155cc3e4d035735d3dd5ece8", "0x00000000000000000000000000000000002d7d473cac1a15d0fee8b22c1a7b3e", "0x1a4249b90be4602c8ff40c7c276160ee41b2a0f8a238ce7706e9face2db03d48", "0x162204b9d54d3ffd285c393a5a1ff76ee681474fd780a21a3cf7fac5c24fc2b9", "0x30279eb953d8ee79b2155c69c04e6443c5de6bf7e02886256dd7b3cd3c9502a4", "0x0d32c1bd21baf43e72d5d82d461ef54833807ff81a877adc822f27a6db88d754", "0x0fe15e055c0803d5ebe6dd77689b70cfd82138f008810ce24535c992daaff27d", "0x1fba82c012671212ce2fc13fd09bf8fba4f7d5875ab8d37495d1ccfcff287331", "0x090738a5842fa4d2699b3726aa0dd97cb59569b4be2c6825335ec4969f859dc2", "0x0c6cb72dabbc28abcf4a50c203534e066c29f48c24ca64d672092f263df3f9d7", "0x0f27fbea0d9145f815c288b50fe7e8c10b8185d325b5264624fd57102855d05d", "0x2a815cd3fd1c43c72ee0130465250ff771d1e7be2347e4ada331b83265a03450", "0x148b4ecf2ad7ed17409417086867ee27bc1b0906dbc9cbb3714c285071e2db70", "0x08e700a42b1d6d36ee65f8ebedf47d3a44463ff9fa579dce13b7492e20142c3a", "0x2e23c69521d572ff2152c50f8c9a9191535f4cf37f95f1e0428692e78842b642", "0x14519e0354365923fb41400c19866135b45e975d56a0980260bc99f0390b1d5f", "0x04caded1f05738f736cb5bcf08d785e395e58eb7738523a20638aa16bc51593e", "0x28787eaccd38383215ea21ec02895c32d979f68ca155f534a2e2d377bff6698b", "0x20a1b81fa96c58cf11c5762c5ceb731efdcb081fca2d34d5c463d2cf40e6da18", "0x11789a06fe3bf53833741d180f068d29534d5bb58a5c64b8119542e62b189fb4", "0x23d00fcd032ace719ffcbc513bfa177a55b04377d76455c2788d999d05d011e2", "0x01f0e81b57b4a73cc118e51ede18f8724debf25c2d109db6ef45280f99f1a3fa", "0x156d1c9b61749810de728f259c2c1c1fd4dbff97101426e26087ca461c93307c", "0x1c5d619ac3a478cfd06d5eebfd879960bb321236be173813f5e78d1366d32c69", "0x250cfae4e1dfc551406f1f3d10b649a637dcb7bcb0f6f697994cf96afd35d0c1", "0x242b999f58cf5f53c874d1092bd38725aa9ea076f5bc8f176efa9ea23393874b", "0x2e15748255c4a5e0e9fe38047341b692a967257de27a85a3a38681bc9f1602ea", "0x01ef83886ea7017253699cb6371988eb8e21b4f7023d7479ece4907fe6d4a6fd", "0x08db2dbc271e375b9312f695c59c48f313235b3432cad50921c8d9ad6dd7ad7a", "0x199309f2c2cd45c15a4abb0e6554a1615ff5a6e9488a8d900bbf835fc8f664ef", "0x074be7a3d88e31ab1b59c9208c012bcfb1f85f351c709e68134996891db52b57", "0x301b1011354d2ebf46134fc4d6d734bb6ed8542d719f38f5e09a376a580cad7f", "0x12968f3eccaa27e44f14d5aaac6ecb70c00d040e07536292e685d7cab03fc563", "0x2110a023c8c22fd2ed70270a2d0a265b92a32ce2217ffe1be9a5d7d5c25f512f", "0x1e8cf4c60c53900f0430d5b44de5804fe8b38299bc803beeb4216e1a289cf624", "0x12301cb908ccb28a2616e29b831ec7105b5d3ebf45ff5fe91d50a9dd53a50b52", "0x0f1029ed107d84ff2d6d4a416cbd01da3f3d7bf5b2209ce93ba424f4b85616fc", "0x1b431d016611b8abd684afd9e92331c3325967b1116bfa91d4f44e2f8e2c9fc2", "0x281e335a0fd117064c8ace3f01e02b134a19e9b9220571ebfaaaa0e3a12d34db", "0x22559c106f77e2ae95677d5e38e288343e3b7168371aec7d3aaab9ef8150af70", "0x13f113b1d9b590149cf08c3f6e90589cda5c7b98528866b891256cb9d5d814e7", "0x10252ef388e4c80246962e98b9e976fab2cd25e1e6f1e3fd2a7d4786c5218a97", "0x16b890723dfdebd9912a9207255f95cb800222165b6fae97ec46e461f23e83f3", "0x25caf77c7d2e8e069341ec90f3c8f6d64319cfd2d77cab0625cf0377285ba11c", "0x016c84288b0bc3c50eebbe250cdd5a4ee50b2c65a24ac64d0c930cbdecb95141", "0x20a537c045b069d47dc6315f45b391f60681222381e5059ec7c8b17bf677d911", "0x2594c0edfcd4064d215a3d797bc8e3b2f401c61f3961ae96ccbec8f8fd29e81f", "0x1c831d7047483ca00ed59bdb84c47ffb8bbebbae92aa164c7b35fcffbb8a35d3", "0x2ea7f60de52b8cd6b0bd06f861fc1f2c5ed1d1fbfa53caccdb836400a03df434", "0x275c6c8bd115f7d2ce196439e2330fad305c6745bab0bf1ce3f2fa32dadc3c43", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x2b3f4e210619347288731e7f0eea1ae60dd8696fe87319044864d099a03a9536", "0x0fecd3d2aebedeb8be2b0b7e3a74de9ec8bd2cb72851541463729e0715aef48b", "0x10bee385ad0c2cd3ff88ef4d630840749e4367f9add4a300fc4f545a7778e92c", "0x1fe792730eeafbd22c4eb80e86e2b40108b1e55b2a08db786289eea5745b9e3b", "0x04d411679da432816b213cd5580dda1fd6c2f258684c036be19b5b26baca583c", "0x159f17b655d2b8a803e0cfb564918628be52d3baa950ca1b127854491624f8f4", "0x225340463867d9252a1269013536e2e1dd219aa18eadef13c324b63d44679334", "0x1885e231554e02abb40ed54b72ebf09b883d0298a6bc06fc645a30365f370ef2", "0x233344517f25170972b8ba35d01f2df2e073d322993abce7df26796126e93498", "0x08990e8faa13b18b4433ec417c5cc596885e11ffd372d5f612c08cc79a5d5c80", "0x1e960a0c892b755c28e21dcbed816c1b182d7da43bae07f8ee622bd4485f79e7", "0x27b58e2ee290a179d349ace82752528b2ff946d60c092b99ef42f53c25d0c99f", "0x2a5cf8a3193107d982edd253002c7a52ab876b445dde8307ab78fbdca022d93c", "0x2b1ab4d5277f8c82750c1c7bd043889b71465ec64a9afc1bfa37d06b1ebd0725", "0x2a0dbf5c4373a58a83d5f2a031ea0615bf12800e33b70c3191a7cbb15966ced8", "0x1f272bb4a19d14a0abdfebc9fc83125e10623b9aef730f8d25f2bf5bead38ea9", "0x2c2339cf0ae7aff56091a568c1e2c3f01f52d8ed13400737fd31eaabcaffb9bd", "0x21f5fefe6b5fa0b5da71089befb74a1a39e52b4f830cb330c3c284e154614dfd", "0x1e6f6ba4b2444586b380dc4e2b3fad111ff1f4754420a846f53ea0789ebfb0ad", "0x1193d170b0b2dd0c4a04331a4b4aa3f12920f182ec3ab547837e30f1116ca584", "0x00000000000000000000000000000025704a15c9e2ce8a69558e7bbcdcbc7784", "0x2e5d36112770fb6c985681cafe40a8c99ad13f702309e7969801dd0ed080e727", "0x0eefc2585f591bb457183134e19ad643966272234d645514bf7868d6dd8ae2cb", "0x300803e4e2339ad39b9c31f228949bbeaf9c74b7101e7be1930b088126247eaa", "0x2bb562a50ed944b438b83b01f200101a34faef7f296a75c84c731755ebddbc1a", "0x1288e0b9c742af39cbcac21357c1b29511b0bbdd3d0e3cf5e14b2eef68a28ab3", "0x20f089131cc96d86ff1cfb67fa3f51670f4bad30158751b2587354bbec76cdf9", "0x1a26c6d3e633f9bf8434cf755b5f1217dad0d455071a97a7bcf85b824f5cf07a", "0x0d7e9b8a51fccf910ec25bdbd13e70b34bd6ea6f4d629fa744f9cdf5f2beb1cf", "0x0b40f28ce428e64df9cf5a024133fc420f39decf5f6af020cc3211ab298d4631", "0x0ca4f189dde7a55fe829f46681232904f6670249a22e0deb47222bd309523a8a", "0x2c544f2e31143783977645edb2a6bdb39b875053963bfa1a5b3ae9de204a7ebe", "0x00aae4454eb48fb18ff60db6b9d015abea2e770a2f7d86d121522b834c791ba5", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x07d74e351fd4cccf4e18475d25211efa8a359066fc693a5c8505ddb507e4b74b", "0x2d9e5bff47207d82533e2445959941181cc890c5779bc7f24d6e8a7b9e425b5c", "0x0aea3c0c317c441a5775a9849108d7a6889b39128235f717b09b184aa08e4eb7", "0x1ca5bc6fb37c55a562f4991901c39902f42d14db71284116df74cb4e7d55e493", "0x220fed26d64cd69f40e6d145a423e4a3c8cd0dce747e7d51647441270ad4d774", "0x15be574c9358889257aa2a30ff7b5fcc31a57da7032296e2c1201c49a44bbdb6", "0x2de539925525bedd3b7f43a9c6bf0f713151a17f79ac7ff4a9cd27b15ffe892a", "0x083086693dbf465211741e2cbff70ff38eb08383faf22d397eb2742c8ad7396a", "0x1fdfa258a890598816e807c50058d7a1462edd5ff196a2eae0f862e454b49aa1", "0x10c434c6daaa8226fa8e3e302123dfdc4455cf68063df518949df5a65a945213", "0x0000000000000000000000000000006472a7874de2c454a4591ed7784df1c104", "0x000000000000000000000000000000000008c46ac53d2c4ad0c26a5d6c790082", "0x0000000000000000000000000000005e422f9cfb8725800de60dfe0a8d4104c0", "0x000000000000000000000000000000000000f10fd4e4de81a0c00073ec91c274", "0x000000000000000000000000000000b20813090eca76bc6aa4a699b1ec8d5d6d", "0x0000000000000000000000000000000000292cc9f8a744eb00e0903c29ce87a7", "0x000000000000000000000000000000350a368b415fbb99fa90a26a42b1a3affd", "0x0000000000000000000000000000000000280eb9275cb05a3435f464d1dc369d", "0x000000000000000000000000000000280df6505e20c7725fe6d29439f96ee05d", "0x000000000000000000000000000000000017ef5033a08535451e2747827aa94b", "0x0000000000000000000000000000002f9ba89ae91b4e4a4ff8ccbd0526faad2f", "0x00000000000000000000000000000000001c2013561dafcc02cb03220bdf23c4", "0x000000000000000000000000000000aac102c400f9e5da0321ded4510994434b", "0x00000000000000000000000000000000001ec8ab9cc834b492fde124962f04a1", "0x0000000000000000000000000000000673dbd698da8b8cce450d2a083aba9987", "0x00000000000000000000000000000000000a49e55bb040249cb41c63cea901cd", "0x000000000000000000000000000000133d92af8d76ee0c74a12081ee7b2ef8c4", "0x0000000000000000000000000000000000240f552d1c6cbb007650e4b142e0a5", "0x000000000000000000000000000000e29c6e7d982ec08d51c79d6261c28d742d", "0x000000000000000000000000000000000021baeec04d9be419c923626034e7b3", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x1e940a528b42d8230e7d4dff76262a80986c0d00b2c02a9bc0559e36212d1547", "0x1ceccf21ac39f70d76ad6f7fe0dcb33b6af04555a0b1959e4714d65925e4e253", "0x096139d757046cdbdb7ee89a95f112f70882a43a46c2f739d9be115dda013420", "0x2f9c8ac67c7825b08eff0e7f7656a671f4c64e5601f2efab35b1b795801eec04", "0x2077e648e1704851cdffd7e6e56311634a7b741bab77ca34d9dff12a6a2bfe99", "0x115d48c4a97aeb3c447a060f9e0d675b0dc7f4a05a3f5776e2f279f3a165d7dc", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000000000fd38c45c3ec5b841482a80e3a56ce82555", "0x00000000000000000000000000000000000ad70b03f092f60af3e0ce1bb29d2c", "0x0000000000000000000000000000007a184d5342c90c634c0b1a050f0b97c9fb", "0x0000000000000000000000000000000000271f42abcb3bc1f0332e4b3ca85e1d", "0x0000000000000000000000000000008256322bbe2c1b8cd9d84e5ff6123477f2", "0x000000000000000000000000000000000025cab962761681dd9547f4c78814df", "0x0000000000000000000000000000008c4234510e5825c02b9ac427bcbf8e279a", "0x000000000000000000000000000000000013a14e0d7fc073c44643af38cc5396"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000040", "0x0000000000000000000000000000000000000000000000000000000000000011", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000003", "0x0000000000000000000000000000000000000000000000000000000000000004", "0x0000000000000000000000000000000000000000000000000000000000000005", "0x0000000000000000000000000000000000000000000000000000000000000006", "0x0000000000000000000000000000000000000000000000000000000000000007", "0x0000000000000000000000000000000000000000000000000000000000000008", "0x0000000000000000000000000000000000000000000000000000000000000009", "0x000000000000000000000000000000000000000000000000000000000000000a", "0x000000000000000000000000000000000000000000000000000000000000000b", "0x000000000000000000000000000000000000000000000000000000000000000c", "0x000000000000000000000000000000000000000000000000000000000000000d", "0x000000000000000000000000000000000000000000000000000000000000000e", "0x000000000000000000000000000000000000000000000000000000000000000f", "0x0000000000000000000000000000000000000000000000000000000000000010", "0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84", "0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae", "0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16", "0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1", "0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c", "0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7", "0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8", "0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c", "0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5", "0x00000000000000000000000000000000002002681bb417184b2df070a16a3858", "0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511", "0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223", "0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7", "0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c", "0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130", "0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f", "0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3", "0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592", "0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3", "0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1", "0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0", "0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c", "0x0000000000000000000000000000009f825dde88092070747180d581c342444a", "0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01", "0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff", "0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9", "0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1", "0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b", "0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2", "0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f", "0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0", "0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349", "0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8", "0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2", "0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556", "0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d", "0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb", "0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d", "0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8", "0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862", "0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e", "0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830", "0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f", "0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe", "0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb", "0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56", "0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc", "0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4", "0x00000000000000000000000000000029a17181c7934fc3fdbd352eac5cb521b9", "0x00000000000000000000000000000000001f497cbf5284ff29a2d336e5991999", "0x000000000000000000000000000000072bd9c0c6beda1fdee6d4ff0432ba9e1b", "0x000000000000000000000000000000000013ea38a0bd2aa751a490a724fac818", "0x000000000000000000000000000000c599f63dcd3edd49f08ae5c3141c1e3493", "0x00000000000000000000000000000000002bdb36be0bea09950dd32a8ccf6fbc", "0x00000000000000000000000000000047f27f29724e7f19eba0340256a0bd4b7d", "0x00000000000000000000000000000000001c1c5ccf87a962129ca785f8f35120", "0x000000000000000000000000000000c5c71efdae00679bbe4a95096e012b1817", "0x000000000000000000000000000000000017a365de041e317817d0135f2b48e0", "0x0000000000000000000000000000008ae711ac402f7848d719c93a89ba8d39f1", "0x00000000000000000000000000000000002b6fb40ed8a1935226f4f9786a0499", "0x0000000000000000000000000000002f03a71501d83de1da5715a4e9462d6198", "0x00000000000000000000000000000000001644064443b8546f48eae693af47b8", "0x00000000000000000000000000000083763ab1b6e8fe269b2fe4c7b9c448c08d", "0x000000000000000000000000000000000021d7cc18c59676a8eeb47c0111c251", "0x000000000000000000000000000000b5f937153073e03ea7d51a996e0ebc2e6b", "0x000000000000000000000000000000000011ddd0e26457373eb06e0493177672", "0x000000000000000000000000000000c5f6eb9f6fc8fa99811a4a88c74a6d018b", "0x000000000000000000000000000000000025bcd07a0732c123567834f5109558", "0x000000000000000000000000000000aeb08a0b1a4442189448b4e97490568146", "0x000000000000000000000000000000000002a1744e4771705536a88f07e0f90f", "0x000000000000000000000000000000b938568293bd0724b0ea76c2ec34c4a829", "0x0000000000000000000000000000000000053296e8f3b9ad3af877dfa9c7c2a7", "0x000000000000000000000000000000f0ca1db6323996eba26bdc86dafef9d10b", "0x00000000000000000000000000000000001441a46c58af03d5645d52721d956a", "0x0000000000000000000000000000008bbf8f884013c66c28ba09c2fbd573b656", "0x0000000000000000000000000000000000206c391ca06fac27d1908e94570243", "0x0000000000000000000000000000002d4f5aaed88ba4f79612d53b804ca8f194", "0x00000000000000000000000000000000001674011c96392df08970fa6b7b4cb8", "0x0000000000000000000000000000009f88297c1729d76c4d9306853598c91325", "0x0000000000000000000000000000000000256f51adfcacc3c1e340be4d32d3e9", "0x0000000000000000000000000000000ab9955eec0d74eb799afed2a802b24d75", "0x00000000000000000000000000000000001fcbe43ea105b30d36ed0b21b03411", "0x000000000000000000000000000000d66b1d5433f1aa5305cd1edce7c22de466", "0x00000000000000000000000000000000002331546a256b8a3b751956806680d4", "0x000000000000000000000000000000e97954ad6cd6f45fb15c91434121db4304", "0x00000000000000000000000000000000002e20a97e09d50f227ced47e7a98250", "0x0000000000000000000000000000001ebbc27eb9ebededefba79522eb58ae89b", "0x0000000000000000000000000000000000090efa4974e566e81d1177b85a30be", "0x0000000000000000000000000000005eafa070b9c9632404052642e3bc14f9fd", "0x00000000000000000000000000000000001489068864102daca6a6b8bc4d448b", "0x0000000000000000000000000000009ebc91aaaac036a6477cadbe54e8556dfd", "0x00000000000000000000000000000000000ef6d835e2ed3343b95c82c8c54037", "0x00000000000000000000000000000033b28b529dff46e93af4e7422530478e4a", "0x000000000000000000000000000000000020a86c2f8591bf190bcddcc03c42fb", "0x000000000000000000000000000000a9679d0acc088f7dc27bf6d866bcd2dda2", "0x00000000000000000000000000000000002fb9d0d2d4099402bed74f738f64cc", "0x00000000000000000000000000000023b09f876a29a061582848a8b9a5870c12", "0x00000000000000000000000000000000001d5bb906f03f0d49e9c4791bc43af9", "0x00000000000000000000000000000017aac9854ea240d8ec97bf760c4d4ba870", "0x00000000000000000000000000000000000b227a556c414ada0dc75bb303e30e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3"] diff --git a/test_programs/execution_success/verify_honk_proof/src/main.nr b/test_programs/execution_success/verify_honk_proof/src/main.nr new file mode 100644 index 00000000000..25f140a9688 --- /dev/null +++ b/test_programs/execution_success/verify_honk_proof/src/main.nr @@ -0,0 +1,21 @@ +// This circuit aggregates a single Honk proof from `assert_statement`. +global SIZE_OF_PROOF_IF_LOGN_IS_28: u32 = 463; +global HONK_IDENTIFIER: u32 = 1; +fn main( + verification_key: [Field; 128], + // 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; SIZE_OF_PROOF_IF_LOGN_IS_28], + 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, +) { + std::verify_proof_with_type( + verification_key, + proof, + public_inputs, + key_hash, + HONK_IDENTIFIER, + ); +} diff --git a/test_programs/execution_success/wildcard_type/Nargo.toml b/test_programs/execution_success/wildcard_type/Nargo.toml new file mode 100644 index 00000000000..e3d7fc636af --- /dev/null +++ b/test_programs/execution_success/wildcard_type/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "wildcard_type" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/wildcard_type/Prover.toml b/test_programs/execution_success/wildcard_type/Prover.toml new file mode 100644 index 00000000000..c7c8371dfa4 --- /dev/null +++ b/test_programs/execution_success/wildcard_type/Prover.toml @@ -0,0 +1 @@ +enable = [4,7] diff --git a/test_programs/execution_success/wildcard_type/src/main.nr b/test_programs/execution_success/wildcard_type/src/main.nr new file mode 100644 index 00000000000..2227dfbf3c7 --- /dev/null +++ b/test_programs/execution_success/wildcard_type/src/main.nr @@ -0,0 +1,23 @@ +struct bar { + enable: [bool; 4], + data: [Field; 2], + pad: u32, +} + +fn main(enable: [Field; 2]) -> pub [Field; 4] { + let mut result = [0; 4]; + let a: [_; 4] = foo(enable[1]); + for i in 0..4 { + result[i] = a[i].data[i % 2]; + } + result +} + +fn foo(x: Field) -> [bar; 4] { + [ + bar { enable: [true, true, false, false], data: [x, x + 1], pad: 0 }, + bar { enable: [true, false, false, false], data: [x + 2, x + 7], pad: 0 }, + bar { enable: [true, true, false, true], data: [x + 3, x + 5], pad: 0 }, + bar { enable: [false, false, false, false], data: [x + 4, x - 1], pad: 0 }, + ] +} 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/execution_success/witness_compression/Prover.toml b/test_programs/execution_success/witness_compression/Prover.toml new file mode 100644 index 00000000000..8c12ebba6cf --- /dev/null +++ b/test_programs/execution_success/witness_compression/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +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/Nargo.toml b/test_programs/execution_success/workspace/Nargo.toml new file mode 100644 index 00000000000..36db098686f --- /dev/null +++ b/test_programs/execution_success/workspace/Nargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["crates/a", "crates/b"] diff --git a/test_programs/execution_success/workspace/crates/a/Nargo.toml b/test_programs/execution_success/workspace/crates/a/Nargo.toml new file mode 100644 index 00000000000..8d0e1aca4a9 --- /dev/null +++ b/test_programs/execution_success/workspace/crates/a/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "a" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/workspace/crates/a/Prover.toml b/test_programs/execution_success/workspace/crates/a/Prover.toml new file mode 100644 index 00000000000..465ef562de4 --- /dev/null +++ b/test_programs/execution_success/workspace/crates/a/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "1" diff --git a/test_programs/execution_success/workspace/crates/a/src/main.nr b/test_programs/execution_success/workspace/crates/a/src/main.nr new file mode 100644 index 00000000000..cf72627da2e --- /dev/null +++ b/test_programs/execution_success/workspace/crates/a/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x == y); +} diff --git a/test_programs/execution_success/workspace/crates/b/Nargo.toml b/test_programs/execution_success/workspace/crates/b/Nargo.toml new file mode 100644 index 00000000000..f316511340f --- /dev/null +++ b/test_programs/execution_success/workspace/crates/b/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "b" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/workspace/crates/b/Prover.toml b/test_programs/execution_success/workspace/crates/b/Prover.toml new file mode 100644 index 00000000000..a0397e89477 --- /dev/null +++ b/test_programs/execution_success/workspace/crates/b/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "0" diff --git a/test_programs/execution_success/workspace/crates/b/src/main.nr b/test_programs/execution_success/workspace/crates/b/src/main.nr new file mode 100644 index 00000000000..4e1fd3c9035 --- /dev/null +++ b/test_programs/execution_success/workspace/crates/b/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x != y); +} diff --git a/test_programs/execution_success/workspace_default_member/Nargo.toml b/test_programs/execution_success/workspace_default_member/Nargo.toml new file mode 100644 index 00000000000..3828c5d0677 --- /dev/null +++ b/test_programs/execution_success/workspace_default_member/Nargo.toml @@ -0,0 +1,3 @@ +[workspace] +members = ["a"] +default-member = "a" diff --git a/test_programs/execution_success/workspace_default_member/Prover.toml b/test_programs/execution_success/workspace_default_member/Prover.toml new file mode 100644 index 00000000000..8c12ebba6cf --- /dev/null +++ b/test_programs/execution_success/workspace_default_member/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "2" diff --git a/test_programs/execution_success/workspace_default_member/a/Nargo.toml b/test_programs/execution_success/workspace_default_member/a/Nargo.toml new file mode 100644 index 00000000000..8d0e1aca4a9 --- /dev/null +++ b/test_programs/execution_success/workspace_default_member/a/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "a" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/workspace_default_member/a/Prover.toml b/test_programs/execution_success/workspace_default_member/a/Prover.toml new file mode 100644 index 00000000000..465ef562de4 --- /dev/null +++ b/test_programs/execution_success/workspace_default_member/a/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "1" diff --git a/test_programs/execution_success/workspace_default_member/a/src/main.nr b/test_programs/execution_success/workspace_default_member/a/src/main.nr new file mode 100644 index 00000000000..cf72627da2e --- /dev/null +++ b/test_programs/execution_success/workspace_default_member/a/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x == y); +} diff --git a/test_programs/execution_success/workspace_default_member/b/Nargo.toml b/test_programs/execution_success/workspace_default_member/b/Nargo.toml new file mode 100644 index 00000000000..f316511340f --- /dev/null +++ b/test_programs/execution_success/workspace_default_member/b/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "b" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/workspace_default_member/b/Prover.toml b/test_programs/execution_success/workspace_default_member/b/Prover.toml new file mode 100644 index 00000000000..83fcd8678e7 --- /dev/null +++ b/test_programs/execution_success/workspace_default_member/b/Prover.toml @@ -0,0 +1,3 @@ +# Deliberately setting these to fail to prove this is NOT executed since a default is specified +x = "1" +y = "1" diff --git a/test_programs/execution_success/workspace_default_member/b/src/main.nr b/test_programs/execution_success/workspace_default_member/b/src/main.nr new file mode 100644 index 00000000000..6e170de75fc --- /dev/null +++ b/test_programs/execution_success/workspace_default_member/b/src/main.nr @@ -0,0 +1,3 @@ +fn main(x : Field, y : pub Field) { + assert(x != y); +} 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..d8345884c82 --- /dev/null +++ b/test_programs/execution_success/wrapping_operations/src/main.nr @@ -0,0 +1,6 @@ +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/execution_success/xor/Nargo.toml b/test_programs/execution_success/xor/Nargo.toml new file mode 100644 index 00000000000..ddf3b6d86c5 --- /dev/null +++ b/test_programs/execution_success/xor/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "xor" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/execution_success/xor/Prover.toml b/test_programs/execution_success/xor/Prover.toml new file mode 100644 index 00000000000..f28f2f8cc48 --- /dev/null +++ b/test_programs/execution_success/xor/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/test_programs/execution_success/xor/src/main.nr b/test_programs/execution_success/xor/src/main.nr new file mode 100644 index 00000000000..4ceef1b518f --- /dev/null +++ b/test_programs/execution_success/xor/src/main.nr @@ -0,0 +1,5 @@ +fn main(x: u32, y: pub u32) { + let m = x ^ y; + + assert(m != 10); +} diff --git a/test_programs/format.sh b/test_programs/format.sh new file mode 100755 index 00000000000..fa63d228752 --- /dev/null +++ b/test_programs/format.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +set -e + +# These tests are incompatible with gas reporting +excluded_dirs=("workspace" "overlapping_dep_and_mod" "overlapping_dep_and_mod_fix" "workspace_default_member" "workspace_reexport_bug") + +# These tests cause failures in CI with a stack overflow for some reason. +ci_excluded_dirs=("eddsa") + +current_dir=$(pwd) + +# 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. + + +function collect_dirs { + test_dirs=$(ls $current_dir/$1) + + for dir in $test_dirs; do + if [[ " ${excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + if [[ ${CI-false} = "true" ]] && [[ " ${ci_excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + echo " \"$1/$dir\"," >> Nargo.toml +done +} + +echo "[workspace]" > Nargo.toml +echo "members = [" >> Nargo.toml + +collect_dirs compile_success_empty +collect_dirs execution_success + +echo "]" >> Nargo.toml + +if [ "$1" == "check" ]; then + nargo fmt --check +else + nargo fmt +fi + + +rm Nargo.toml diff --git a/test_programs/gates_report.sh b/test_programs/gates_report.sh new file mode 100755 index 00000000000..c92346f40e8 --- /dev/null +++ b/test_programs/gates_report.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -e + +BACKEND=${BACKEND:-bb} + +# These tests are incompatible with gas reporting +excluded_dirs=("workspace" "workspace_default_member" "databus" "double_verify_honk_proof" "verify_honk_proof") + +current_dir=$(pwd) +artifacts_path="$current_dir/acir_artifacts" +test_dirs=$(ls $artifacts_path) + +echo "{\"programs\": [" > gates_report.json + +# Bound for checking where to place last parentheses +NUM_ARTIFACTS=$(ls -1q "$artifacts_path" | wc -l) + +ITER="1" +for pathname in $test_dirs; do + ARTIFACT_NAME=$(basename "$pathname") + if [[ " ${excluded_dirs[@]} " =~ "$ARTIFACT_NAME" ]]; then + ITER=$(( $ITER + 1 )) + continue + fi + + GATES_INFO=$($BACKEND gates -b "$artifacts_path/$ARTIFACT_NAME/target/program.json") + MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r ".functions[0] | {package_name: "\"$ARTIFACT_NAME\"", functions: [{name: \"main\", acir_opcodes, opcodes: .acir_opcodes, circuit_size}], unconstrained_functions: []}") + echo -n $MAIN_FUNCTION_INFO >> gates_report.json + + if (($ITER == $NUM_ARTIFACTS)); then + echo "" >> gates_report.json + else + echo "," >> gates_report.json + fi + + ITER=$(( $ITER + 1 )) +done + +echo "]}" >> gates_report.json + + diff --git a/test_programs/gates_report_brillig.sh b/test_programs/gates_report_brillig.sh new file mode 100755 index 00000000000..3f2a4542735 --- /dev/null +++ b/test_programs/gates_report_brillig.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -e + +# These tests are incompatible with gas reporting +excluded_dirs=("workspace" "workspace_default_member" "double_verify_nested_proof" "overlapping_dep_and_mod" "comptime_println") + +current_dir=$(pwd) +base_path="$current_dir/execution_success" +test_dirs=$(ls $base_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 "[workspace]" > Nargo.toml +echo "members = [" >> Nargo.toml + +for dir in $test_dirs; do + if [[ " ${excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + if [[ ${CI-false} = "true" ]] && [[ " ${ci_excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + echo " \"execution_success/$dir\"," >> Nargo.toml +done + +echo "]" >> Nargo.toml + +nargo info --silence-warnings --force-brillig --json --inliner-aggressiveness $1 | jq -r ".programs[].functions = []" > gates_report_brillig.json + +rm Nargo.toml diff --git a/test_programs/gates_report_brillig_execution.sh b/test_programs/gates_report_brillig_execution.sh new file mode 100755 index 00000000000..c6a904f8b93 --- /dev/null +++ b/test_programs/gates_report_brillig_execution.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +set -e + +# These tests are incompatible with gas reporting +excluded_dirs=( + "workspace" + "workspace_default_member" + "double_verify_nested_proof" + "overlapping_dep_and_mod" + "comptime_println" + # bit sizes for bigint operation doesn't match up. + "bigint" + # Expected to fail as test asserts on which runtime it is in. + "is_unconstrained" +) + +current_dir=$(pwd) +base_path="$current_dir/execution_success" +test_dirs=$(ls $base_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 "[workspace]" > Nargo.toml +echo "members = [" >> Nargo.toml + +for dir in $test_dirs; do + if [[ " ${excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + if [[ ${CI-false} = "true" ]] && [[ " ${ci_excluded_dirs[@]} " =~ " ${dir} " ]]; then + continue + fi + + if [[ ! -f "${base_path}/${dir}/Nargo.toml" ]]; then + continue + fi + + echo " \"execution_success/$dir\"," >> Nargo.toml +done + +echo "]" >> Nargo.toml + +nargo info --silence-warnings --profile-execution --json --inliner-aggressiveness $1 | jq -r ".programs[].functions = []" > gates_report_brillig_execution.json + +rm Nargo.toml diff --git a/test_programs/memory_report.sh b/test_programs/memory_report.sh new file mode 100755 index 00000000000..4ba7579b390 --- /dev/null +++ b/test_programs/memory_report.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +set -e + +sudo apt-get install heaptrack + +NARGO="nargo" +PARSE_MEMORY=$(realpath "$(dirname "$0")/parse_memory.sh") + + +# Tests to be profiled for memory report +tests_to_profile=("keccak256" "workspace" "regression_4709" "ram_blowup_regression") + +current_dir=$(pwd) +base_path="$current_dir/execution_success" + +# If there is an argument that means we want to generate a report for only the current directory +if [ "$1" == "1" ]; then + base_path="$current_dir" + tests_to_profile=(".") +fi + +FIRST="1" + +FLAGS=${FLAGS:- ""} +echo "{\"memory_reports\": [ " > memory_report.json + +for test_name in ${tests_to_profile[@]}; do + cd $base_path/$test_name + + if [ $FIRST = "1" ] + then + FIRST="0" + else + echo " ," >> $current_dir"/memory_report.json" + fi + + if [ "$1" == "1" ]; then + test_name=$(basename $current_dir) + fi + + COMMAND="compile --force --silence-warnings $FLAGS" + if [ "$2" == "1" ]; then + COMMAND="execute --silence-warnings" + fi + + heaptrack --output $current_dir/$test_name"_heap" $NARGO $COMMAND + if test -f $current_dir/$test_name"_heap.gz"; + then + heaptrack --analyze $current_dir/$test_name"_heap.gz" > $current_dir/$test_name"_heap_analysis.txt" + rm $current_dir/$test_name"_heap.gz" + else + heaptrack --analyze $current_dir/$test_name"_heap.zst" > $current_dir/$test_name"_heap_analysis.txt" + rm $current_dir/$test_name"_heap.zst" + fi + consumption="$(grep 'peak heap memory consumption' $current_dir/$test_name'_heap_analysis.txt')" + len=${#consumption}-30 + peak=${consumption:30:len} + rm $current_dir/$test_name"_heap_analysis.txt" + peak_memory=$($PARSE_MEMORY $peak) + echo -e " {\n \"artifact_name\":\"$test_name\",\n \"peak_memory\":\"$peak_memory\"\n }" >> $current_dir"/memory_report.json" +done + +echo "]}" >> $current_dir"/memory_report.json" + diff --git a/test_programs/noir_test_failure/should_fail_mismatch/Nargo.toml b/test_programs/noir_test_failure/should_fail_mismatch/Nargo.toml new file mode 100644 index 00000000000..3d2cf2c6096 --- /dev/null +++ b/test_programs/noir_test_failure/should_fail_mismatch/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "should_fail_with_mismatch" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr b/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr new file mode 100644 index 00000000000..59b99c85c0b --- /dev/null +++ b/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr @@ -0,0 +1,10 @@ +#[test(should_fail_with = "Not equal")] +fn test_different_string() { + assert_eq(0, 1, "Different string"); +} + +// The failure reason is a substring of the expected message, but it should be the other way around +#[test(should_fail_with = "Definitely Not equal!")] +fn test_wrong_expectation() { + assert_eq(0, 1, "Not equal"); +} 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/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/assert_message/Nargo.toml b/test_programs/noir_test_success/assert_message/Nargo.toml new file mode 100644 index 00000000000..667035339bd --- /dev/null +++ b/test_programs/noir_test_success/assert_message/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_message" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/test_programs/noir_test_success/assert_message/src/main.nr b/test_programs/noir_test_success/assert_message/src/main.nr new file mode 100644 index 00000000000..073e42daf4a --- /dev/null +++ b/test_programs/noir_test_success/assert_message/src/main.nr @@ -0,0 +1,15 @@ +// Have to use inputs otherwise the ACIR gets optimized away due to constants. +// With the original ACIR the optimizations can rearrange or merge opcodes, +// which might end up getting out of sync with assertion messages. +#[test(should_fail_with = "first")] +fn test_assert_message_preserved_during_optimization(a: Field, b: Field, c: Field) { + if (a + b) * (a - b) != c { + assert((a + b) * (a - b) == c, "first"); + assert((a - b) * (a + b) == c, "second"); + assert((a + b) * (a - b) == c, "third"); + assert((2 * a + b) * (a - b / 2) == c * c, "fourth"); + } else { + // The fuzzer might have generated a passing test. + assert((a + b) * (a - b) != c, "first"); + } +} diff --git a/test_programs/noir_test_success/bounded_vec/Nargo.toml b/test_programs/noir_test_success/bounded_vec/Nargo.toml new file mode 100644 index 00000000000..0d58f5872ef --- /dev/null +++ b/test_programs/noir_test_success/bounded_vec/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bounded_vec" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/bounded_vec/src/main.nr b/test_programs/noir_test_success/bounded_vec/src/main.nr new file mode 100644 index 00000000000..fa2c55e6934 --- /dev/null +++ b/test_programs/noir_test_success/bounded_vec/src/main.nr @@ -0,0 +1,272 @@ +#[test] +fn test_vec_new_good() { + good(); +} + +#[test(should_fail)] +fn test_vec_new_bad() { + bad(); +} + +// docs:start:new_example +fn good() -> 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 `good`'s return value + v2 +} + +fn bad() { + // Error: Type annotation needed + // The compiler can't infer `MaxLen` from this code. + let mut v3 = BoundedVec::new(); + v3.push(5); +} +// docs:end:new_example + +#[test] +fn test_vec_push_pop() { + let mut vec: BoundedVec = BoundedVec::new(); + assert(vec.len == 0); + vec.push(2); + assert(vec.len == 1); + vec.push(4); + assert(vec.len == 2); + vec.push(6); + assert(vec.len == 3); + let x = vec.pop(); + assert(x == 6); + assert(vec.len == 2); + assert(vec.get(0) == 2); + 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)] +// docs:start:set_unchecked_example +fn set_unchecked_example() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2]); + + // Here we're safely writing within the valid range of `vec` + // `vec` now has the value [42, 2] + vec.set_unchecked(0, 42); + + // We can then safely read this value back out of `vec`. + // Notice that we use the checked version of `get` which would prevent reading unsafe values. + assert_eq(vec.get(0), 42); + + // We've now written past the end of `vec`. + // As this index is still within the maximum potential length of `v`, + // it won't cause a constraint failure. + vec.set_unchecked(2, 42); + println(vec); + + // This will write past the end of the maximum potential length of `vec`, + // it will then trigger a constraint failure. + vec.set_unchecked(5, 42); + println(vec); +} +// docs:end:set_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")] +fn test_vec_extend_from_array_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4, 6]); +} + +#[test(should_fail_with = "extend_from_array out of bounds")] +fn test_vec_extend_from_array_twice_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2]); + assert(vec.len == 1); + vec.extend_from_array([4, 6]); +} + +#[test(should_fail)] +fn test_vec_get_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4]); + let _x = vec.get(2); +} + +#[test(should_fail)] +fn test_vec_get_not_declared() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2]); + let _x = vec.get(1); +} + +#[test(should_fail)] +fn test_vec_get_uninitialized() { + let mut vec: BoundedVec = BoundedVec::new(); + let _x = vec.get(0); +} + +#[test(should_fail_with = "push out of bounds")] +fn test_vec_push_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.push(1); + vec.push(2); +} + +#[test(should_fail_with = "extend_from_bounded_vec out of bounds")] +fn test_vec_extend_from_bounded_vec_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(); + + let mut another_vec: BoundedVec = BoundedVec::new(); + another_vec.extend_from_array([1, 2, 3]); + + vec.extend_from_bounded_vec(another_vec); +} + +#[test(should_fail_with = "extend_from_bounded_vec out of bounds")] +fn test_vec_extend_from_bounded_vec_twice_out_of_bound() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2]); + + let mut another_vec: BoundedVec = BoundedVec::new(); + another_vec.push(3); + + vec.extend_from_bounded_vec(another_vec); +} + +#[test] +fn test_vec_any() { + // 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] +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)); +} + diff --git a/test_programs/noir_test_success/brillig_oracle/Nargo.toml b/test_programs/noir_test_success/brillig_oracle/Nargo.toml new file mode 100644 index 00000000000..13bd913cef7 --- /dev/null +++ b/test_programs/noir_test_success/brillig_oracle/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_oracle" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/noir_test_success/brillig_oracle/src/main.nr b/test_programs/noir_test_success/brillig_oracle/src/main.nr new file mode 100644 index 00000000000..77dbeef9aa1 --- /dev/null +++ b/test_programs/noir_test_success/brillig_oracle/src/main.nr @@ -0,0 +1,53 @@ +use std::slice; +use std::test::OracleMock; + +#[test] +fn test_main() { + main(10); +} + +// Tests oracle usage in brillig/unconstrained functions +fn main(_x: Field) { + /// Safety: testing context + unsafe { + let size = 20; + // TODO: Add a method along the lines of `(0..size).to_array()`. + let mut mock_oracle_response = [0; 20]; + // TODO: Add an `array.reverse()` method. + let mut reversed_mock_oracle_response = [0; 20]; + for i in 0..size { + mock_oracle_response[i] = i; + reversed_mock_oracle_response[19 - i] = i; + } + + // TODO: this method of returning a slice feels hacky. + let _ = OracleMock::mock("get_number_sequence").with_params(size).returns(( + 20, mock_oracle_response, + )); + let _ = OracleMock::mock("get_reverse_number_sequence").with_params(size).returns(( + 20, reversed_mock_oracle_response, + )); + + get_number_sequence_wrapper(size as Field); + } +} + +// Define oracle functions which we have mocked above +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} + +#[oracle(get_reverse_number_sequence)] +unconstrained fn get_reverse_number_sequence(_size: Field) -> [Field] {} + +unconstrained fn get_number_sequence_wrapper(size: Field) { + let slice = get_number_sequence(size); + for i in 0..20 as u32 { + assert(slice[i] == i as Field); + } + + let reversed_slice = get_reverse_number_sequence(size); + // Regression test that we have not overwritten memory + for i in 0..20 as u32 { + assert(slice[i] == reversed_slice[19 - i]); + } +} diff --git a/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..35a0c44218f --- /dev/null +++ b/test_programs/noir_test_success/brillig_overflow_checks/src/main.nr @@ -0,0 +1,23 @@ +use 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_blackbox/Nargo.toml b/test_programs/noir_test_success/comptime_blackbox/Nargo.toml new file mode 100644 index 00000000000..5eac6f3c91a --- /dev/null +++ b/test_programs/noir_test_success/comptime_blackbox/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_blackbox" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] diff --git a/test_programs/noir_test_success/comptime_blackbox/src/main.nr b/test_programs/noir_test_success/comptime_blackbox/src/main.nr new file mode 100644 index 00000000000..859790f7d2d --- /dev/null +++ b/test_programs/noir_test_success/comptime_blackbox/src/main.nr @@ -0,0 +1,157 @@ +//! Tests to show that the comptime interpreter implement blackbox functions. +use std::bigint; +use std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}; + +/// Test that all bigint operations work in comptime. +#[test] +fn test_bigint() { + let result: [u8] = comptime { + let a = bigint::Secpk1Fq::from_le_bytes(&[0, 1, 2, 3, 4]); + let b = bigint::Secpk1Fq::from_le_bytes(&[5, 6, 7, 8, 9]); + let c = (a + b) * b / a - a; + c.to_le_bytes() + }; + // Do the same calculation outside comptime. + let a = bigint::Secpk1Fq::from_le_bytes(&[0, 1, 2, 3, 4]); + let b = bigint::Secpk1Fq::from_le_bytes(&[5, 6, 7, 8, 9]); + let c = bigint::Secpk1Fq::from_le_bytes(result); + assert_eq(c, (a + b) * b / a - a); +} + +/// Test that to_le_radix returns an array. +#[test] +fn test_to_le_radix() { + comptime { + let field = 2; + let bytes: [u8; 8] = field.to_le_radix(256); + let _num = bigint::BigInt::from_le_bytes(bytes, bigint::bn254_fq); + }; +} + +#[test] +fn test_bitshift() { + let c = comptime { + let a: i32 = 10; + let b: u32 = 4; + a << b as u8 + }; + assert_eq(c, 160); +} + +#[test] +fn test_aes128_encrypt() { + let ciphertext = comptime { + let plaintext: [u8; 5] = [1, 2, 3, 4, 5]; + let iv: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let key: [u8; 16] = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]; + std::aes128::aes128_encrypt(plaintext, iv, key) + }; + let clear_len = 5; + let cipher_len = clear_len + 16 - clear_len % 16; + assert_eq(ciphertext.len(), cipher_len); +} + +#[test] +fn test_blake2s() { + let hash = comptime { + let input = [104, 101, 108, 108, 111]; + std::hash::blake2s(input) + }; + assert_eq(hash[0], 0x19); + assert_eq(hash[31], 0x25); +} + +#[test] +fn test_blake3() { + let hash = comptime { + let input = [104, 101, 108, 108, 111]; + std::hash::blake3(input) + }; + assert_eq(hash[0], 0xea); + assert_eq(hash[31], 0x0f); +} + +/// Test that ecdsa_secp256k1 is implemented. +#[test] +fn test_ecdsa_secp256k1() { + let (valid_array, valid_slice) = comptime { + let pub_key_x: [u8; 32] = hex_to_bytes("a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7").as_array(); + let pub_key_y: [u8; 32] = hex_to_bytes("893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7").as_array(); + let signature: [u8; 64] = hex_to_bytes("e5081c80ab427dc370346f4a0e31aa2bad8d9798c38061db9ae55a4e8df454fd28119894344e71b78770cc931d61f480ecbb0b89d6eb69690161e49a715fcd55").as_array(); + let hashed_message: [u8; 32] = hex_to_bytes("3a73f4123a5cd2121f21cd7e8d358835476949d035d9c2da6806b4633ac8c1e2").as_array(); + + let valid_array = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + let valid_slice = std::ecdsa_secp256k1::verify_signature_slice(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); + + (valid_array, valid_slice) + }; + assert(valid_array); + assert(valid_slice); +} + +/// Test that ecdsa_secp256r1 is implemented. +#[test] +fn test_ecdsa_secp256r1() { + let (valid_array, valid_slice) = comptime { + let pub_key_x: [u8; 32] = hex_to_bytes("550f471003f3df97c3df506ac797f6721fb1a1fb7b8f6f83d224498a65c88e24").as_array(); + let pub_key_y: [u8; 32] = hex_to_bytes("136093d7012e509a73715cbd0b00a3cc0ff4b5c01b3ffa196ab1fb327036b8e6").as_array(); + let signature: [u8; 64] = hex_to_bytes("2c70a8d084b62bfc5ce03641caf9f72ad4da8c81bfe6ec9487bb5e1bef62a13218ad9ee29eaf351fdc50f1520c425e9b908a07278b43b0ec7b872778c14e0784").as_array(); + let hashed_message: [u8; 32] = hex_to_bytes("54705ba3baafdbdfba8c5f9a70f7a89bee98d906b53e31074da7baecdc0da9ad").as_array(); + + let valid_array = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + let valid_slice = std::ecdsa_secp256r1::verify_signature_slice(pub_key_x, pub_key_y, signature, hashed_message.as_slice()); + (valid_array, valid_slice) + }; + assert(valid_array); + assert(valid_slice); +} + +/// Test that sha256_compression is implemented. +#[test] +fn test_sha256() { + let hash = comptime { + let input: [u8; 1] = [0xbd]; + std::hash::sha256(input) + }; + assert_eq(hash[0], 0x68); + assert_eq(hash[31], 0x2b); +} + +/// Test that `embedded_curve_add` and `multi_scalar_mul` are implemented. +#[test] +fn test_embedded_curve_ops() { + let (sum, mul) = comptime { + let s1 = EmbeddedCurveScalar { lo: 1, hi: 0 }; + let s2 = EmbeddedCurveScalar { lo: 2, hi: 0 }; + let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; + let g2 = multi_scalar_mul([g1], [s2]); + let sum = g1 + g2; + let mul = multi_scalar_mul([g1, g2], [s1, s1]); + (sum, mul) + }; + assert_eq(sum, mul); +} + +/// Parse a lowercase hexadecimal string (without 0x prefix) as byte slice. +comptime fn hex_to_bytes(s: str) -> [u8] { + assert(N % 2 == 0); + let mut out = &[]; + let bz = s.as_bytes(); + let mut h: u32 = 0; + for i in 0 .. bz.len() { + let ascii = bz[i]; + let d = if ascii < 58 { + ascii - 48 + } else { + assert(ascii >= 97); // enforce >= 'a' + assert(ascii <= 102); // enforce <= 'f' + ascii - 87 + }; + h = h * 16 + d as u32; + if i % 2 == 1 { + out = out.push_back(h as u8); + h = 0; + } + } + out +} diff --git a/test_programs/noir_test_success/comptime_expr/Nargo.toml b/test_programs/noir_test_success/comptime_expr/Nargo.toml new file mode 100644 index 00000000000..a40da9c5f28 --- /dev/null +++ b/test_programs/noir_test_success/comptime_expr/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_expr" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/noir_test_success/comptime_expr/src/main.nr b/test_programs/noir_test_success/comptime_expr/src/main.nr new file mode 100644 index 00000000000..25910685e87 --- /dev/null +++ b/test_programs/noir_test_success/comptime_expr/src/main.nr @@ -0,0 +1,772 @@ +mod tests { + use std::meta::op::BinaryOp; + use std::meta::op::UnaryOp; + + #[test] + fn test_expr_as_array() { + comptime { + let expr = quote { [1, 2, 4] }.as_expr().unwrap(); + let elems = expr.as_array().unwrap(); + assert_eq(elems.len(), 3); + assert_eq(elems[0].as_integer().unwrap(), (1, false)); + assert_eq(elems[1].as_integer().unwrap(), (2, false)); + assert_eq(elems[2].as_integer().unwrap(), (4, false)); + } + } + + #[test] + fn test_expr_modify_for_array() { + comptime { + let expr = quote { [1, 2, 4] }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let elems = expr.as_array().unwrap(); + assert_eq(elems.len(), 3); + assert_eq(elems[0].as_integer().unwrap(), (2, false)); + assert_eq(elems[1].as_integer().unwrap(), (4, false)); + assert_eq(elems[2].as_integer().unwrap(), (8, false)); + } + } + + #[test] + fn test_expr_as_assert() { + comptime { + let expr = quote { assert(true) }.as_expr().unwrap(); + let (predicate, msg) = expr.as_assert().unwrap(); + assert_eq(predicate.as_bool().unwrap(), true); + assert(msg.is_none()); + + let expr = quote { assert(false, "oops") }.as_expr().unwrap(); + let (predicate, msg) = expr.as_assert().unwrap(); + assert_eq(predicate.as_bool().unwrap(), false); + assert(msg.is_some()); + } + } + + #[test] + fn test_expr_modify_for_assert() { + comptime { + let expr = quote { assert(1) }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (predicate, msg) = expr.as_assert().unwrap(); + assert_eq(predicate.as_integer().unwrap(), (2, false)); + assert(msg.is_none()); + + let expr = quote { assert(1, 2) }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (predicate, msg) = expr.as_assert().unwrap(); + assert_eq(predicate.as_integer().unwrap(), (2, false)); + assert_eq(msg.unwrap().as_integer().unwrap(), (4, false)); + } + } + + #[test] + fn test_expr_as_assert_eq() { + comptime { + let expr = quote { assert_eq(true, false) }.as_expr().unwrap(); + let (lhs, rhs, msg) = expr.as_assert_eq().unwrap(); + assert_eq(lhs.as_bool().unwrap(), true); + assert_eq(rhs.as_bool().unwrap(), false); + assert(msg.is_none()); + + let expr = quote { assert_eq(false, true, "oops") }.as_expr().unwrap(); + let (lhs, rhs, msg) = expr.as_assert_eq().unwrap(); + assert_eq(lhs.as_bool().unwrap(), false); + assert_eq(rhs.as_bool().unwrap(), true); + assert(msg.is_some()); + } + } + + #[test] + fn test_expr_modify_for_assert_eq() { + comptime { + let expr = quote { assert_eq(1, 2) }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (lhs, rhs, msg) = expr.as_assert_eq().unwrap(); + assert_eq(lhs.as_integer().unwrap(), (2, false)); + assert_eq(rhs.as_integer().unwrap(), (4, false)); + assert(msg.is_none()); + + let expr = quote { assert_eq(1, 2, 3) }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (lhs, rhs, msg) = expr.as_assert_eq().unwrap(); + assert_eq(lhs.as_integer().unwrap(), (2, false)); + assert_eq(rhs.as_integer().unwrap(), (4, false)); + assert_eq(msg.unwrap().as_integer().unwrap(), (6, false)); + } + } + + #[test] + fn test_expr_as_assign() { + comptime { + let expr = quote { { a = 1; } }.as_expr().unwrap(); + let exprs = expr.as_block().unwrap(); + let (_lhs, rhs) = exprs[0].as_assign().unwrap(); + assert_eq(rhs.as_integer().unwrap(), (1, false)); + } + } + + #[test] + fn test_expr_modify_for_assign() { + comptime { + let expr = quote { { a = 1; } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let exprs = expr.as_block().unwrap(); + let (_lhs, rhs) = exprs[0].as_assign().unwrap(); + assert_eq(rhs.as_integer().unwrap(), (2, false)); + } + } + + #[test] + fn test_expr_as_block() { + comptime { + let expr = quote { { 1; 4; 23 } }.as_expr().unwrap(); + let exprs = expr.as_block().unwrap(); + assert_eq(exprs.len(), 3); + assert_eq(exprs[0].as_integer().unwrap(), (1, false)); + assert_eq(exprs[1].as_integer().unwrap(), (4, false)); + assert_eq(exprs[2].as_integer().unwrap(), (23, false)); + + assert(exprs[0].has_semicolon()); + assert(exprs[1].has_semicolon()); + assert(!exprs[2].has_semicolon()); + } + } + + #[test] + fn test_expr_modify_for_block() { + comptime { + let expr = quote { { 1; 4; 23 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let exprs = expr.as_block().unwrap(); + assert_eq(exprs.len(), 3); + assert_eq(exprs[0].as_integer().unwrap(), (2, false)); + assert_eq(exprs[1].as_integer().unwrap(), (8, false)); + assert_eq(exprs[2].as_integer().unwrap(), (46, false)); + + assert(exprs[0].has_semicolon()); + assert(exprs[1].has_semicolon()); + assert(!exprs[2].has_semicolon()); + } + } + + #[test] + fn test_expr_as_method_call() { + comptime { + let expr = quote { foo.bar::(3, 4) }.as_expr().unwrap(); + let (_object, name, generics, arguments) = expr.as_method_call().unwrap(); + + assert_eq(name, quote { bar }); + + assert_eq(generics.len(), 1); + assert(generics[0].is_field()); + + assert_eq(arguments.len(), 2); + assert_eq(arguments[0].as_integer().unwrap(), (3, false)); + assert_eq(arguments[1].as_integer().unwrap(), (4, false)); + } + } + + #[test] + fn test_expr_modify_for_method_call() { + comptime { + let expr = quote { foo.bar(3, 4) }.as_expr().unwrap(); + let expr = expr.modify(times_two); + + let (_object, name, generics, arguments) = expr.as_method_call().unwrap(); + + assert_eq(name, quote { bar }); + + assert_eq(generics.len(), 0); + + assert_eq(arguments.len(), 2); + assert_eq(arguments[0].as_integer().unwrap(), (6, false)); + assert_eq(arguments[1].as_integer().unwrap(), (8, false)); + } + } + + #[test] + fn test_expr_as_integer() { + comptime { + let expr = quote { 1 }.as_expr().unwrap(); + assert_eq((1, false), expr.as_integer().unwrap()); + + let expr = quote { -2 }.as_expr().unwrap(); + assert_eq((2, true), expr.as_integer().unwrap()); + } + } + + #[test] + fn test_expr_modify_for_integer() { + comptime { + let expr = quote { 1 }.as_expr().unwrap(); + let expr = expr.modify(times_two); + + assert_eq((2, false), expr.as_integer().unwrap()); + } + } + + #[test] + fn test_expr_as_binary_op() { + comptime { + assert(get_binary_op(quote { x + y }).is_add()); + assert(get_binary_op(quote { x - y }).is_subtract()); + assert(get_binary_op(quote { x * y }).is_multiply()); + assert(get_binary_op(quote { x / y }).is_divide()); + assert(get_binary_op(quote { x == y }).is_equal()); + assert(get_binary_op(quote { x != y }).is_not_equal()); + assert(get_binary_op(quote { x < y }).is_less_than()); + assert(get_binary_op(quote { x <= y }).is_less_than_or_equal()); + assert(get_binary_op(quote { x > y }).is_greater_than()); + assert(get_binary_op(quote { x >= y }).is_greater_than_or_equal()); + assert(get_binary_op(quote { x & y }).is_and()); + assert(get_binary_op(quote { x | y }).is_or()); + assert(get_binary_op(quote { x ^ y }).is_xor()); + assert(get_binary_op(quote { x >> y }).is_shift_right()); + assert(get_binary_op(quote { x << y }).is_shift_left()); + assert(get_binary_op(quote { x % y }).is_modulo()); + } + } + + #[test] + fn test_expr_modify_for_binary_op() { + comptime { + let expr = quote { 3 + 4 }.as_expr().unwrap(); + let expr = expr.modify(times_two); + + let (lhs, op, rhs) = expr.as_binary_op().unwrap(); + assert_eq(lhs.as_integer().unwrap(), (6, false)); + assert(op.is_add()); + assert_eq(rhs.as_integer().unwrap(), (8, false)); + } + } + + #[test] + fn test_expr_as_bool() { + comptime { + let expr = quote { false }.as_expr().unwrap(); + assert(expr.as_bool().unwrap() == false); + + let expr = quote { true }.as_expr().unwrap(); + assert_eq(expr.as_bool().unwrap(), true); + } + } + + #[test] + fn test_expr_as_cast() { + comptime { + let expr = quote { 1 as Field }.as_expr().unwrap(); + let (expr, typ) = expr.as_cast().unwrap(); + assert_eq(expr.as_integer().unwrap(), (1, false)); + assert(typ.is_field()); + } + } + + #[test] + fn test_expr_modify_for_cast() { + comptime { + let expr = quote { 1 as Field }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (expr, typ) = expr.as_cast().unwrap(); + assert_eq(expr.as_integer().unwrap(), (2, false)); + assert(typ.is_field()); + } + } + + #[test] + fn test_expr_as_comptime() { + comptime { + let expr = quote { comptime { 1; 4; 23 } }.as_expr().unwrap(); + let exprs = expr.as_comptime().unwrap(); + assert_eq(exprs.len(), 3); + } + } + + #[test] + fn test_expr_modify_for_comptime() { + comptime { + let expr = quote { comptime { 1; 4; 23 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let exprs = expr.as_comptime().unwrap(); + assert_eq(exprs.len(), 3); + assert_eq(exprs[0].as_integer().unwrap(), (2, false)); + } + } + + #[test] + fn test_expr_as_comptime_as_statement() { + comptime { + let expr = quote { { comptime { 1; 4; 23 } } }.as_expr().unwrap(); + let exprs = expr.as_block().unwrap(); + assert_eq(exprs.len(), 1); + + let exprs = exprs[0].as_comptime().unwrap(); + assert_eq(exprs.len(), 3); + } + } + + #[test] + fn test_expr_as_constructor() { + comptime { + let expr = quote { Foo { a: 1, b: 2 } }.as_expr().unwrap(); + let (_typ, fields) = expr.as_constructor().unwrap(); + assert_eq(fields.len(), 2); + assert_eq(fields[0].0, quote { a }); + assert_eq(fields[0].1.as_integer().unwrap(), (1, false)); + assert_eq(fields[1].0, quote { b }); + assert_eq(fields[1].1.as_integer().unwrap(), (2, false)); + } + } + + #[test] + fn test_expr_modify_for_constructor() { + comptime { + let expr = quote { foo::bar::Baz:: { a: 1, b: 2 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (_typ, fields) = expr.as_constructor().unwrap(); + assert_eq(fields.len(), 2); + assert_eq(fields[0].0, quote { a }); + assert_eq(fields[0].1.as_integer().unwrap(), (2, false)); + assert_eq(fields[1].0, quote { b }); + assert_eq(fields[1].1.as_integer().unwrap(), (4, false)); + } + } + + // This test can't only be around the comptime block since that will cause + // `nargo fmt` to remove the comptime keyword. + // docs:start:as_expr_example + #[test] + fn test_expr_as_function_call() { + comptime { + let expr = quote { foo(42) }.as_expr().unwrap(); + let (_function, args) = expr.as_function_call().unwrap(); + assert_eq(args.len(), 1); + assert_eq(args[0].as_integer().unwrap(), (42, false)); + } + } + // docs:end:as_expr_example + + #[test] + fn test_expr_modify_for_function_call() { + comptime { + let expr = quote { foo(42) }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (_function, args) = expr.as_function_call().unwrap(); + assert_eq(args.len(), 1); + assert_eq(args[0].as_integer().unwrap(), (84, false)); + } + } + + #[test] + fn test_expr_as_if() { + comptime { + let expr = quote { if 1 { 2 } }.as_expr().unwrap(); + let (_condition, _consequence, alternative) = expr.as_if().unwrap(); + assert(alternative.is_none()); + + let expr = quote { if 1 { 2 } else { 3 } }.as_expr().unwrap(); + let (_condition, _consequence, alternative) = expr.as_if().unwrap(); + assert(alternative.is_some()); + } + } + + #[test] + fn test_expr_modify_for_if() { + comptime { + let expr = quote { if 1 { 2 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (condition, consequence, alternative) = expr.as_if().unwrap(); + assert_eq(condition.as_integer().unwrap(), (2, false)); + let consequence = consequence.as_block().unwrap()[0].as_block().unwrap()[0]; + assert_eq(consequence.as_integer().unwrap(), (4, false)); + assert(alternative.is_none()); + + let expr = quote { if 1 { 2 } else { 3 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (condition, consequence, alternative) = expr.as_if().unwrap(); + assert_eq(condition.as_integer().unwrap(), (2, false)); + let consequence = consequence.as_block().unwrap()[0].as_block().unwrap()[0]; + assert_eq(consequence.as_integer().unwrap(), (4, false)); + let alternative = alternative.unwrap().as_block().unwrap()[0].as_block().unwrap()[0]; + assert_eq(alternative.as_integer().unwrap(), (6, false)); + } + } + + #[test] + fn test_expr_as_index() { + comptime { + let expr = quote { foo[bar] }.as_expr().unwrap(); + assert(expr.as_index().is_some()); + } + } + + #[test] + fn test_expr_modify_for_index() { + comptime { + let expr = quote { 1[2] }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (object, index) = expr.as_index().unwrap(); + assert_eq(object.as_integer().unwrap(), (2, false)); + assert_eq(index.as_integer().unwrap(), (4, false)); + } + } + + #[test] + fn test_expr_as_member_access() { + comptime { + let expr = quote { foo.bar }.as_expr().unwrap(); + let (_, name) = expr.as_member_access().unwrap(); + assert_eq(name, quote { bar }); + } + } + + #[test] + fn test_expr_modify_for_member_access() { + comptime { + let expr = quote { 1.bar }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (expr, name) = expr.as_member_access().unwrap(); + assert_eq(name, quote { bar }); + assert_eq(expr.as_integer().unwrap(), (2, false)); + } + } + + #[test] + fn test_expr_as_member_access_with_an_lvalue() { + comptime { + let expr = quote { { foo.bar = 1; } }.as_expr().unwrap(); + let exprs = expr.as_block().unwrap(); + let (lhs, _rhs) = exprs[0].as_assign().unwrap(); + let (_, name) = lhs.as_member_access().unwrap(); + assert_eq(name, quote { bar }); + } + } + + #[test] + fn test_expr_as_repeated_element_array() { + comptime { + let expr = quote { [1; 3] }.as_expr().unwrap(); + let (expr, length) = expr.as_repeated_element_array().unwrap(); + assert_eq(expr.as_integer().unwrap(), (1, false)); + assert_eq(length.as_integer().unwrap(), (3, false)); + } + } + + #[test] + fn test_expr_modify_for_repeated_element_array() { + comptime { + let expr = quote { [1; 3] }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (expr, length) = expr.as_repeated_element_array().unwrap(); + assert_eq(expr.as_integer().unwrap(), (2, false)); + assert_eq(length.as_integer().unwrap(), (6, false)); + } + } + + #[test] + fn test_expr_as_repeated_element_slice() { + comptime { + let expr = quote { &[1; 3] }.as_expr().unwrap(); + let (expr, length) = expr.as_repeated_element_slice().unwrap(); + assert_eq(expr.as_integer().unwrap(), (1, false)); + assert_eq(length.as_integer().unwrap(), (3, false)); + } + } + + #[test] + fn test_expr_modify_for_repeated_element_slice() { + comptime { + let expr = quote { &[1; 3] }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (expr, length) = expr.as_repeated_element_slice().unwrap(); + assert_eq(expr.as_integer().unwrap(), (2, false)); + assert_eq(length.as_integer().unwrap(), (6, false)); + } + } + + #[test] + fn test_expr_as_slice() { + comptime { + let expr = quote { &[1, 3, 5] }.as_expr().unwrap(); + let elems = expr.as_slice().unwrap(); + assert_eq(elems.len(), 3); + assert_eq(elems[0].as_integer().unwrap(), (1, false)); + assert_eq(elems[1].as_integer().unwrap(), (3, false)); + assert_eq(elems[2].as_integer().unwrap(), (5, false)); + } + } + + #[test] + fn test_expr_modify_for_slice() { + comptime { + let expr = quote { &[1, 3, 5] }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let elems = expr.as_slice().unwrap(); + assert_eq(elems.len(), 3); + assert_eq(elems[0].as_integer().unwrap(), (2, false)); + assert_eq(elems[1].as_integer().unwrap(), (6, false)); + assert_eq(elems[2].as_integer().unwrap(), (10, false)); + } + } + + #[test] + fn test_expr_as_tuple() { + comptime { + let expr = quote { (1, 2) }.as_expr().unwrap(); + let tuple_exprs = expr.as_tuple().unwrap(); + assert_eq(tuple_exprs.len(), 2); + } + } + + #[test] + fn test_expr_modify_for_tuple() { + comptime { + let expr = quote { (1, 2) }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let tuple_exprs = expr.as_tuple().unwrap(); + assert_eq(tuple_exprs.len(), 2); + assert_eq(tuple_exprs[0].as_integer().unwrap(), (2, false)); + assert_eq(tuple_exprs[1].as_integer().unwrap(), (4, false)); + } + } + + #[test] + fn test_expr_as_unary_op() { + comptime { + assert(get_unary_op(quote { -x }).is_minus()); + assert(get_unary_op(quote { !x }).is_not()); + assert(get_unary_op(quote { &mut x }).is_mutable_reference()); + assert(get_unary_op(quote { *x }).is_dereference()); + } + } + + #[test] + fn test_expr_modify_for_unary_op() { + comptime { + let expr = quote { -(1) }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (op, expr) = expr.as_unary_op().unwrap(); + assert(op.is_minus()); + assert_eq(expr.as_integer().unwrap(), (2, false)); + } + } + + #[test] + fn test_expr_as_unsafe() { + comptime { + let expr = quote { + /// Safety: test + unsafe { 1; 4; 23 } + } + .as_expr() + .unwrap(); + let exprs = expr.as_unsafe().unwrap(); + assert_eq(exprs.len(), 3); + } + } + + #[test] + fn test_expr_modify_for_unsafe() { + comptime { + let expr = quote { + /// Safety: test + unsafe { 1; 4; 23 } + } + .as_expr() + .unwrap(); + let expr = expr.modify(times_two); + let exprs = expr.as_unsafe().unwrap(); + assert_eq(exprs.len(), 3); + assert_eq(exprs[0].as_integer().unwrap(), (2, false)); + } + } + + #[test] + fn test_expr_is_break() { + comptime { + let expr = quote { { break; } }.as_expr().unwrap(); + let exprs = expr.as_block().unwrap(); + assert(exprs[0].is_break()); + } + } + + #[test] + fn test_expr_is_continue() { + comptime { + let expr = quote { { continue; } }.as_expr().unwrap(); + let exprs = expr.as_block().unwrap(); + assert(exprs[0].is_continue()); + } + } + + #[test] + fn test_expr_as_lambda() { + comptime { + let expr = quote { |x: Field| -> Field { 1 } }.as_expr().unwrap(); + let (params, return_type, body) = expr.as_lambda().unwrap(); + assert_eq(params.len(), 1); + assert(params[0].1.unwrap().is_field()); + assert(return_type.unwrap().is_field()); + assert_eq(body.as_block().unwrap()[0].as_integer().unwrap(), (1, false)); + + let expr = quote { |x| { 1 } }.as_expr().unwrap(); + let (params, return_type, body) = expr.as_lambda().unwrap(); + assert_eq(params.len(), 1); + assert(params[0].1.is_none()); + assert(return_type.is_none()); + assert_eq(body.as_block().unwrap()[0].as_integer().unwrap(), (1, false)); + } + } + + #[test] + fn test_expr_modify_lambda() { + comptime { + let expr = quote { |x: Field| -> Field { 1 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (params, return_type, body) = expr.as_lambda().unwrap(); + assert_eq(params.len(), 1); + assert(params[0].1.unwrap().is_field()); + assert(return_type.unwrap().is_field()); + assert_eq( + body.as_block().unwrap()[0].as_block().unwrap()[0].as_integer().unwrap(), + (2, false), + ); + + let expr = quote { |x| { 1 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (params, return_type, body) = expr.as_lambda().unwrap(); + assert_eq(params.len(), 1); + assert(params[0].1.is_none()); + assert(return_type.is_none()); + assert_eq( + body.as_block().unwrap()[0].as_block().unwrap()[0].as_integer().unwrap(), + (2, false), + ); + } + } + + #[test] + fn test_expr_as_let() { + comptime { + let expr = quote { let x: Field = 1; }.as_expr().unwrap(); + let (_pattern, typ, expr) = expr.as_let().unwrap(); + assert(typ.unwrap().is_field()); + assert_eq(expr.as_integer().unwrap(), (1, false)); + } + } + + #[test] + fn test_expr_modify_for_let() { + comptime { + let expr = quote { let x : Field = 1; }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (_pattern, typ, expr) = expr.as_let().unwrap(); + assert(typ.unwrap().is_field()); + assert_eq(expr.as_integer().unwrap(), (2, false)); + } + } + + #[test] + fn test_expr_modify_for_let_without_type() { + comptime { + let expr = quote { let x = 1; }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (_pattern, typ, expr) = expr.as_let().unwrap(); + assert(typ.is_none()); + assert_eq(expr.as_integer().unwrap(), (2, false)); + } + } + + #[test] + fn test_expr_as_for_statement() { + comptime { + let expr = quote { for x in 2 { 3 } }.as_expr().unwrap(); + let (index, array, body) = expr.as_for().unwrap(); + assert_eq(index, quote { x }); + assert_eq(array.as_integer().unwrap(), (2, false)); + assert_eq(body.as_block().unwrap()[0].as_integer().unwrap(), (3, false)); + } + } + + #[test] + fn test_expr_modify_for_statement() { + comptime { + let expr = quote { for x in 2 { 3 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (index, array, body) = expr.as_for().unwrap(); + assert_eq(index, quote { x }); + assert_eq(array.as_integer().unwrap(), (4, false)); + assert_eq( + body.as_block().unwrap()[0].as_block().unwrap()[0].as_integer().unwrap(), + (6, false), + ); + } + } + + #[test] + fn test_expr_as_for_range_statement() { + comptime { + let expr = quote { for x in 2..3 { 4 } }.as_expr().unwrap(); + let (index, from, to, body) = expr.as_for_range().unwrap(); + assert_eq(index, quote { x }); + assert_eq(from.as_integer().unwrap(), (2, false)); + assert_eq(to.as_integer().unwrap(), (3, false)); + assert_eq(body.as_block().unwrap()[0].as_integer().unwrap(), (4, false)); + } + } + + #[test] + fn test_expr_modify_for_range_statement() { + comptime { + let expr = quote { for x in 2..3 { 4 } }.as_expr().unwrap(); + let expr = expr.modify(times_two); + let (index, from, to, body) = expr.as_for_range().unwrap(); + assert_eq(index, quote { x }); + assert_eq(from.as_integer().unwrap(), (4, false)); + assert_eq(to.as_integer().unwrap(), (6, false)); + assert_eq( + body.as_block().unwrap()[0].as_block().unwrap()[0].as_integer().unwrap(), + (8, false), + ); + } + } + + #[test] + fn test_automatically_unwraps_parenthesized_expression() { + comptime { + let expr = quote { ((if 1 { 2 })) }.as_expr().unwrap(); + assert(expr.as_if().is_some()); + } + } + + #[test] + fn test_resolve_to_function_definition() { + comptime { + let expr = quote { times_two }.as_expr().unwrap(); + let func = expr.resolve(Option::none()).as_function_definition().unwrap(); + assert_eq(func.name(), quote { times_two }); + assert_eq(func.parameters().len(), 1); + } + } + + comptime fn get_unary_op(quoted: Quoted) -> UnaryOp { + let expr = quoted.as_expr().unwrap(); + let (op, _) = expr.as_unary_op().unwrap(); + op + } + + comptime fn get_binary_op(quoted: Quoted) -> BinaryOp { + let expr = quoted.as_expr().unwrap(); + let (_, op, _) = expr.as_binary_op().unwrap(); + op + } + + comptime fn times_two(expr: Expr) -> Option { + expr.as_integer().and_then(|integer: (Field, bool)| { + let (value, _) = integer; + let value = value * 2; + quote { $value }.as_expr() + }) + } +} + +fn main() {} 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..95c54b96609 --- /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. +comptime 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..760df58c34a --- /dev/null +++ b/test_programs/noir_test_success/embedded_curve_ops/src/main.nr @@ -0,0 +1,36 @@ +use std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}; + +#[test] + + fn test_infinite_point() { + let zero = EmbeddedCurvePoint::point_at_infinity(); + 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.is_infinite); + assert(g1 + zero == g1); + assert(g1 - g1 == zero); + assert(g1 - zero == g1); + assert(zero + zero == zero); + assert( + multi_scalar_mul([g1], [s1]) + == EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false } + ); + assert(multi_scalar_mul([g1, g1], [s1, s1]) == g2); + assert( + multi_scalar_mul( + [g1, zero], + [EmbeddedCurveScalar { lo: 2, hi: 0 }, EmbeddedCurveScalar { lo: 42, hi: 25 }] + ) + == g2 + ); + assert( + multi_scalar_mul( + [g1, g1, zero], + [s1, s1, EmbeddedCurveScalar { lo: 42, hi: 25 }] + ) + == g2 + ); +} diff --git a/test_programs/noir_test_success/field_comparisons/Nargo.toml b/test_programs/noir_test_success/field_comparisons/Nargo.toml new file mode 100644 index 00000000000..e819464ca68 --- /dev/null +++ b/test_programs/noir_test_success/field_comparisons/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "field_comparisons" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/noir_test_success/field_comparisons/src/main.nr b/test_programs/noir_test_success/field_comparisons/src/main.nr new file mode 100644 index 00000000000..8613e6d6c4f --- /dev/null +++ b/test_programs/noir_test_success/field_comparisons/src/main.nr @@ -0,0 +1,16 @@ +use std::field::bn254::{TWO_POW_128, assert_gt}; + +#[test(should_fail)] +fn test_assert_gt_should_fail_eq() { + assert_gt(0, 0); +} + +#[test(should_fail)] +fn test_assert_gt_should_fail_low_lt() { + assert_gt(0, 0x100); +} + +#[test(should_fail)] +fn test_assert_gt_should_fail_high_lt() { + assert_gt(TWO_POW_128, TWO_POW_128 + 0x100); +} diff --git a/test_programs/noir_test_success/fuzzer_checks/Nargo.toml b/test_programs/noir_test_success/fuzzer_checks/Nargo.toml new file mode 100644 index 00000000000..cd09d0d344d --- /dev/null +++ b/test_programs/noir_test_success/fuzzer_checks/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "fuzzer_checks" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/noir_test_success/fuzzer_checks/src/main.nr b/test_programs/noir_test_success/fuzzer_checks/src/main.nr new file mode 100644 index 00000000000..70e5e29b855 --- /dev/null +++ b/test_programs/noir_test_success/fuzzer_checks/src/main.nr @@ -0,0 +1,9 @@ +#[test(should_fail_with = "42 is not allowed")] +fn finds_magic_value(x: u32) { + let x = x as u64; + if x == 21 { + assert(2 * x != 42, "42 is not allowed"); + } else { + assert(2 * x == 42, "42 is not allowed"); + } +} diff --git a/test_programs/noir_test_success/global_eval/Nargo.toml b/test_programs/noir_test_success/global_eval/Nargo.toml new file mode 100644 index 00000000000..1dfe3a9660a --- /dev/null +++ b/test_programs/noir_test_success/global_eval/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "global_eval" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] diff --git a/test_programs/noir_test_success/global_eval/src/main.nr b/test_programs/noir_test_success/global_eval/src/main.nr new file mode 100644 index 00000000000..6ec366c4cd6 --- /dev/null +++ b/test_programs/noir_test_success/global_eval/src/main.nr @@ -0,0 +1,20 @@ +use std::uint128::U128; + +// These definitions require `to_be_bits` and `to_le_bits` to be supported at comptime. +global BITS_BE_13: [u1; 4] = (13 as Field).to_be_bits(); +global BITS_LE_13: [u1; 4] = (13 as Field).to_le_bits(); + +// Examples from #6691 which use the above behind the scenes. +global POW64_A: Field = 2.pow_32(64); +global POW64_B: Field = (U128::one() << 64).to_integer(); + +#[test] +fn test_be_and_le_bits() { + assert_eq(BITS_BE_13, [1,1,0,1]); + assert_eq(BITS_LE_13, [1,0,1,1]); +} + +#[test] +fn test_pow64() { + assert_eq(POW64_A, POW64_B); +} 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..aaf2c87ddb0 --- /dev/null +++ b/test_programs/noir_test_success/mock_oracle/src/main.nr @@ -0,0 +1,154 @@ +use 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() { + /// Safety: testing context + unsafe { + OracleMock::mock("void_field"); + void_field(); // Some return value must be set + } +} + +#[test] +fn test_mock() { + /// Safety: testing context + unsafe { + OracleMock::mock("void_field").returns(10); + assert_eq(void_field(), 10); + } +} + +#[test] +fn test_multiple_mock() { + /// Safety: testing context + unsafe { + 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() { + /// Safety: testing context + unsafe { + 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() { + /// Safety: testing context + unsafe { + OracleMock::mock("field_field").with_params((5,)).returns(10); + assert_eq(field_field(5), 10); + } +} + +#[test] +fn test_multiple_mock_with_params() { + /// Safety: testing context + unsafe { + 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() { + /// Safety: testing context + unsafe { + 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() { + /// Safety: testing context + unsafe { + 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 }; + + /// Safety: testing context + unsafe { + 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/Nargo.toml b/test_programs/noir_test_success/out_of_bounds_alignment/Nargo.toml new file mode 100644 index 00000000000..e535c113f20 --- /dev/null +++ b/test_programs/noir_test_success/out_of_bounds_alignment/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "out_of_bounds_alignment" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/noir_test_success/out_of_bounds_alignment/src/main.nr b/test_programs/noir_test_success/out_of_bounds_alignment/src/main.nr new file mode 100644 index 00000000000..05bc2a5ce13 --- /dev/null +++ b/test_programs/noir_test_success/out_of_bounds_alignment/src/main.nr @@ -0,0 +1,23 @@ +fn out_of_bounds(arr_1: [Field; 50]) -> Field { + arr_1[50 + 1] +} + +unconstrained fn out_of_bounds_unconstrained_wrapper( + arr_1: [Field; 50], + arr_2: [Field; 50], +) -> Field { + out_of_bounds(arr_1) +} + +#[test(should_fail)] +fn test_acir() { + assert_eq(out_of_bounds([0; 50]), 0); +} + +#[test(should_fail)] +fn test_brillig() { + /// Safety: testing context + unsafe { + assert_eq(out_of_bounds_unconstrained_wrapper([0; 50], [0; 50]), 0); + } +} diff --git a/test_programs/noir_test_success/regression_4080/Nargo.toml b/test_programs/noir_test_success/regression_4080/Nargo.toml new file mode 100644 index 00000000000..a38baf389d6 --- /dev/null +++ b/test_programs/noir_test_success/regression_4080/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "regression_4080" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/noir_test_success/regression_4080/src/main.nr b/test_programs/noir_test_success/regression_4080/src/main.nr new file mode 100644 index 00000000000..781d3e33ea3 --- /dev/null +++ b/test_programs/noir_test_success/regression_4080/src/main.nr @@ -0,0 +1,8 @@ +// This test checks that `var^var` is assigned the correct type. +// https://github.com/noir-lang/noir/issues/4080 + +#[test(should_fail_with = "attempt to add with overflow")] +fn main() { + let var1: u8 = ((255 + 1) ^ (255 + 1)) - ((255 + 1) - (255 + 1)); + assert_eq(var1, 0); +} diff --git a/test_programs/noir_test_success/regression_4561/Nargo.toml b/test_programs/noir_test_success/regression_4561/Nargo.toml new file mode 100644 index 00000000000..90deee74640 --- /dev/null +++ b/test_programs/noir_test_success/regression_4561/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_4561" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/noir_test_success/regression_4561/src/main.nr b/test_programs/noir_test_success/regression_4561/src/main.nr new file mode 100644 index 00000000000..6a8b4bd61fb --- /dev/null +++ b/test_programs/noir_test_success/regression_4561/src/main.nr @@ -0,0 +1,78 @@ +// Regression test for issue #4561 +use std::test::OracleMock; + +type TReturnElem = [Field; 3]; +type TReturn = [TReturnElem; 2]; + +#[oracle(simple_nested_return)] +unconstrained fn simple_nested_return_oracle() -> TReturn {} + +unconstrained fn simple_nested_return_unconstrained() -> TReturn { + simple_nested_return_oracle() +} + +#[test] +unconstrained fn test_simple_nested_return() { + OracleMock::mock("simple_nested_return").returns([1, 2, 3, 4, 5, 6]); + assert_eq(simple_nested_return_unconstrained(), [[1, 2, 3], [4, 5, 6]]); +} + +#[oracle(nested_with_fields_return)] +unconstrained fn nested_with_fields_return_oracle() -> (Field, TReturn, Field) {} + +unconstrained fn nested_with_fields_return_unconstrained() -> (Field, TReturn, Field) { + nested_with_fields_return_oracle() +} + +#[test] +unconstrained fn test_nested_with_fields_return() { + OracleMock::mock("nested_with_fields_return").returns((0, [1, 2, 3, 4, 5, 6], 7)); + assert_eq(nested_with_fields_return_unconstrained(), (0, [[1, 2, 3], [4, 5, 6]], 7)); +} + +#[oracle(two_nested_return)] +unconstrained fn two_nested_return_oracle() -> (Field, TReturn, Field, TReturn) {} + +unconstrained fn two_nested_return_unconstrained() -> (Field, TReturn, Field, TReturn) { + two_nested_return_oracle() +} + +#[test] +unconstrained fn two_nested_return() { + OracleMock::mock("two_nested_return").returns((0, [1, 2, 3, 4, 5, 6], 7, [1, 2, 3, 4, 5, 6])); + assert_eq(two_nested_return_unconstrained(), (0, [[1, 2, 3], [4, 5, 6]], 7, [[1, 2, 3], [4, 5, 6]])); +} + +#[oracle(foo_return)] +unconstrained fn foo_return() -> (Field, TReturn, TestTypeFoo) {} +unconstrained fn foo_return_unconstrained() -> (Field, TReturn, TestTypeFoo) { + foo_return() +} + +struct TestTypeFoo { + a: Field, + b: [[[Field; 3]; 4]; 2], + c: [TReturnElem; 2], + d: TReturnElem, +} + +#[test] +unconstrained fn complexe_struct_return() { + OracleMock::mock("foo_return").returns( + ( + 0, [1, 2, 3, 4, 5, 6], 7, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [1, 2, 3, 4, 5, 6] + ) + ); + let foo_x = foo_return_unconstrained(); + assert_eq((foo_x.0, foo_x.1), (0, [[1, 2, 3], [4, 5, 6]])); + assert_eq(foo_x.2.a, 7); + assert_eq( + foo_x.2.b, [ + [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18], [19, 20, 21], [22, 23, 24]] + ] + ); + let a: TReturnElem = [1, 2, 3]; + let b: TReturnElem = [4, 5, 6]; + assert_eq(foo_x.2.c, [a, b]); + assert_eq(foo_x.2.d, a); +} diff --git a/test_programs/noir_test_success/should_fail_with_matches/Nargo.toml b/test_programs/noir_test_success/should_fail_with_matches/Nargo.toml new file mode 100644 index 00000000000..21bce3d2b2d --- /dev/null +++ b/test_programs/noir_test_success/should_fail_with_matches/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "should_fail_with_match" +type = "bin" +authors = [""] +[dependencies] 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 new file mode 100644 index 00000000000..42696762ffe --- /dev/null +++ b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr @@ -0,0 +1,93 @@ +#[test(should_fail_with = "Not equal")] +fn test_should_fail_with_match() { + assert_eq(0, 1, "Not equal"); +} + +#[test(should_fail_with = "Not equal")] +fn test_should_fail_with_match_partial_match() { + assert_eq(0, 1, "Definitely Not equal!"); +} + +#[test(should_fail)] +fn test_should_fail_without_match() { + assert_eq(0, 1); +} + +#[test(should_fail_with = "Not equal")] +fn test_should_fail_with_runtime_match() { + assert_eq(std::hash::pedersen_commitment([27]).x, 0, "Not equal"); +} + +#[test(should_fail)] +fn test_should_fail_without_runtime_match() { + assert_eq(std::hash::pedersen_commitment([27]).x, 0); +} + +struct InvalidPointError { + point: 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 = 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 = 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_with = "Not equal")] +unconstrained fn unconstrained_test_should_fail_with_match_partial_match() { + assert_eq(0, 1, "Definitely 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(std::hash::pedersen_commitment([27]).x, 0, "Not equal"); +} + +#[test(should_fail)] +unconstrained fn unconstrained_test_should_fail_without_runtime_match() { + assert_eq(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 = 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 = std::hash::pedersen_commitment([27]); + assert_eq(hash.x, 0, f"Invalid hash: {hash}"); +} diff --git a/test_programs/parse_memory.sh b/test_programs/parse_memory.sh new file mode 100755 index 00000000000..f2af7548e9f --- /dev/null +++ b/test_programs/parse_memory.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -e + +# This script accepts a string representing the amount of memory allocatedas outputted by `heaptrack` +# and standardizes it to be in terms of megabytes as `heaptrack` will report different units depending on the duration. + +DIGITS='([0-9]+(\.[0-9]+)?)' +KILOBYTES_REGEX=^${DIGITS}K$ +MEGABYTES_REGEX=^${DIGITS}M$ +GIGABYTES_REGEX=^${DIGITS}G$ + +if [[ $1 =~ $KILOBYTES_REGEX ]]; then + echo ${BASH_REMATCH[1]} 1000 | awk '{printf "%.3f\n", $1/$2}' +elif [[ $1 =~ $MEGABYTES_REGEX ]]; then + echo ${BASH_REMATCH[1]} | awk '{printf "%.3f\n", $1}' +elif [[ $1 =~ $GIGABYTES_REGEX ]]; then + echo ${BASH_REMATCH[1]} 1000 | awk '{printf "%.3f\n", $1/$2}' +else + echo "Could not parse memory: unrecognized format" 1>&2 + exit 1 +fi diff --git a/test_programs/parse_time.sh b/test_programs/parse_time.sh new file mode 100755 index 00000000000..2ff5c259cd2 --- /dev/null +++ b/test_programs/parse_time.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -e + +# This script accepts a string representing the time spent within a span as outputted by `tracing` +# and standardizes it to be in terms of seconds as `tracing` will report different units depending on the duration. + +DIGITS='([0-9]+(\.[0-9]+)?)' +MICROSECONDS_REGEX=^${DIGITS}µs$ +MILLISECONDS_REGEX=^${DIGITS}ms$ +SECONDS_REGEX=^${DIGITS}s$ + +if [[ $1 =~ $MICROSECONDS_REGEX ]]; then + echo ${BASH_REMATCH[1]} 1000000 | awk '{printf "%.3f\n", $1/$2}' +elif [[ $1 =~ $MILLISECONDS_REGEX ]]; then + echo ${BASH_REMATCH[1]} 1000 | awk '{printf "%.3f\n", $1/$2}' +elif [[ $1 =~ $SECONDS_REGEX ]]; then + echo ${BASH_REMATCH[1]} | awk '{printf "%.3f\n", $1}' +else + echo "Could not parse time: unrecognized format" 1>&2 + exit 1 +fi \ No newline at end of file diff --git a/test_programs/rebuild.sh b/test_programs/rebuild.sh new file mode 100755 index 00000000000..e5badbd2ea6 --- /dev/null +++ b/test_programs/rebuild.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +# Exit immediately if a command exits with a non-zero status, treat unset variables as an error, and print commands as they are executed +set -e + +process_dir() { + local dir=$1 + local current_dir=$2 + local dir_name=$(basename "$dir") + + { + echo "Processing $dir" + + if [[ ! -f "$dir/Nargo.toml" ]]; then + echo "No Nargo.toml found in $dir. Removing directory." + rm -rf "$dir" + echo "$dir: skipped (no Nargo.toml)" + return 0 + fi + + if [[ ! -d "$current_dir/acir_artifacts/$dir_name" ]]; then + mkdir -p "$current_dir/acir_artifacts/$dir_name" + fi + + cd "$dir" + if [ -d ./target/ ]; then + rm -r ./target/ + fi + + if ! nargo execute witness; then + echo "$dir failed" + else + 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" + mkdir "$current_dir/acir_artifacts/$dir_name/proofs" + + mv ./target/$dir_name.json "$current_dir/acir_artifacts/$dir_name/target/program.json" + mv ./target/*.gz "$current_dir/acir_artifacts/$dir_name/target/" + echo "$dir succeeded" + fi + + cd "$current_dir" + } >> "$current_dir/rebuild.log" 2>&1 +} + +export -f process_dir + +excluded_dirs=("workspace" "workspace_default_member") +current_dir=$(pwd) +base_path="$current_dir/execution_success" +dirs_to_process=() + +# Remove existing artifacts and create a new directory +rm -rf "$current_dir/acir_artifacts" +mkdir -p "$current_dir/acir_artifacts" + +# Gather directories to process, either from arguments or by default. +if [ $# -gt 0 ]; then + for dir in "$@"; do + dirs_to_process+=("$base_path/$dir") + done +else + for dir in $base_path/*; do + if [[ ! -d $dir ]] || [[ " ${excluded_dirs[@]} " =~ " $(basename "$dir") " ]]; then + continue + fi + dirs_to_process+=("$dir") + done + + for dir in $current_dir/benchmarks/*; do + if [[ ! -d $dir ]]; then + continue + fi + dirs_to_process+=("$dir") + done +fi + +# Clear any existing rebuild.log +rm -f "$current_dir/rebuild.log" + +# Process directories in parallel +parallel -j7 process_dir {} "$current_dir" ::: ${dirs_to_process[@]} + +# Check rebuild.log for failures +if [ -f "$current_dir/rebuild.log" ]; then + failed_dirs=($(grep -a 'failed' "$current_dir/rebuild.log" | awk '{print $1}')) +else + echo "rebuild.log not found or empty. Check for errors." >&2 + exit 1 +fi + +# Print final status message after processing all directories +if [ ${#failed_dirs[@]} -ne 0 ]; then + echo "Rebuild failed for the following directories:" + for dir in "${failed_dirs[@]}"; do + echo "- $dir" + done + exit 1 +else + echo "Rebuild Succeeded!" +fi diff --git a/test_programs/test_libraries/bad_impl/Nargo.toml b/test_programs/test_libraries/bad_impl/Nargo.toml new file mode 100644 index 00000000000..62ffe95922d --- /dev/null +++ b/test_programs/test_libraries/bad_impl/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "bad_impl" +type = "lib" +authors = [""] +[dependencies] diff --git a/test_programs/test_libraries/bad_impl/src/lib.nr b/test_programs/test_libraries/bad_impl/src/lib.nr new file mode 100644 index 00000000000..a96a6cbf91f --- /dev/null +++ b/test_programs/test_libraries/bad_impl/src/lib.nr @@ -0,0 +1,5 @@ +impl Field { + fn something(self) -> Field { + self + } +} diff --git a/test_programs/test_libraries/bad_name/Nargo.toml b/test_programs/test_libraries/bad_name/Nargo.toml new file mode 100644 index 00000000000..74f6f66524d --- /dev/null +++ b/test_programs/test_libraries/bad_name/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "bad-name" +type = "lib" +authors = [""] +[dependencies] diff --git a/test_programs/test_libraries/bad_name/src/lib.nr b/test_programs/test_libraries/bad_name/src/lib.nr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_programs/test_libraries/bin_dep/Nargo.toml b/test_programs/test_libraries/bin_dep/Nargo.toml new file mode 100644 index 00000000000..7cc99c1c5c5 --- /dev/null +++ b/test_programs/test_libraries/bin_dep/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "bin_dep" +type = "bin" +authors = [""] +[dependencies] diff --git a/test_programs/test_libraries/bin_dep/src/main.nr b/test_programs/test_libraries/bin_dep/src/main.nr new file mode 100644 index 00000000000..042c85a8afb --- /dev/null +++ b/test_programs/test_libraries/bin_dep/src/main.nr @@ -0,0 +1,3 @@ +fn call_dep1_then_dep2(x: Field, y: Field) { + assert(x == y); +} diff --git a/test_programs/test_libraries/diamond_deps_1/Nargo.toml b/test_programs/test_libraries/diamond_deps_1/Nargo.toml new file mode 100644 index 00000000000..f7770e07469 --- /dev/null +++ b/test_programs/test_libraries/diamond_deps_1/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "diamond_deps_1" +type = "lib" +authors = [""] +[dependencies] +dep2 = { path = "../diamond_deps_2" } diff --git a/test_programs/test_libraries/diamond_deps_1/src/lib.nr b/test_programs/test_libraries/diamond_deps_1/src/lib.nr new file mode 100644 index 00000000000..d76ce5a05e9 --- /dev/null +++ b/test_programs/test_libraries/diamond_deps_1/src/lib.nr @@ -0,0 +1,5 @@ +use dep2::call_dep2; + +pub fn call_dep1_then_dep2(x: Field, y: Field) -> Field { + call_dep2(x, y) +} diff --git a/test_programs/test_libraries/diamond_deps_2/Nargo.toml b/test_programs/test_libraries/diamond_deps_2/Nargo.toml new file mode 100644 index 00000000000..2dbba1b7a9e --- /dev/null +++ b/test_programs/test_libraries/diamond_deps_2/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "diamond_deps_2" +type = "lib" +authors = [""] +[dependencies] diff --git a/test_programs/test_libraries/diamond_deps_2/src/lib.nr b/test_programs/test_libraries/diamond_deps_2/src/lib.nr new file mode 100644 index 00000000000..23de4d4c0f3 --- /dev/null +++ b/test_programs/test_libraries/diamond_deps_2/src/lib.nr @@ -0,0 +1,5 @@ +global RESOLVE_THIS: Field = 3; + +pub fn call_dep2(x: Field, y: Field) -> Field { + x + y +} diff --git a/test_programs/test_libraries/exporting_lib/Nargo.toml b/test_programs/test_libraries/exporting_lib/Nargo.toml new file mode 100644 index 00000000000..628418c0608 --- /dev/null +++ b/test_programs/test_libraries/exporting_lib/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "exporting_lib" +type = "lib" +authors = [""] + +[dependencies] diff --git a/test_programs/test_libraries/exporting_lib/src/lib.nr b/test_programs/test_libraries/exporting_lib/src/lib.nr new file mode 100644 index 00000000000..7da75ce5413 --- /dev/null +++ b/test_programs/test_libraries/exporting_lib/src/lib.nr @@ -0,0 +1,9 @@ +pub struct MyStruct { + pub inner: Field +} + +pub type FooStruct = MyStruct; + +pub fn is_struct_zero(val: MyStruct) -> bool { + val.inner == 0 +} diff --git a/test_programs/test_libraries/reexporting_lib/Nargo.toml b/test_programs/test_libraries/reexporting_lib/Nargo.toml new file mode 100644 index 00000000000..c26ce501e56 --- /dev/null +++ b/test_programs/test_libraries/reexporting_lib/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "reexporting_lib" +type = "lib" +authors = [""] + +[dependencies] +exporting_lib = { path = "../exporting_lib" } diff --git a/test_programs/test_libraries/reexporting_lib/src/lib.nr b/test_programs/test_libraries/reexporting_lib/src/lib.nr new file mode 100644 index 00000000000..f106971028d --- /dev/null +++ b/test_programs/test_libraries/reexporting_lib/src/lib.nr @@ -0,0 +1,3 @@ +pub use exporting_lib::{MyStruct, FooStruct}; + +pub use exporting_lib as lib; diff --git a/tooling/acvm_cli/Cargo.toml b/tooling/acvm_cli/Cargo.toml new file mode 100644 index 00000000000..06dd5e676bd --- /dev/null +++ b/tooling/acvm_cli/Cargo.toml @@ -0,0 +1,41 @@ +[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 + +[lints] +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.workspace = true +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.workspace = true +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..e5d48073ca8 --- /dev/null +++ b/tooling/acvm_cli/src/cli/execute_cmd.rs @@ -0,0 +1,93 @@ +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 nargo::PrintOutput; + +use crate::cli::fs::inputs::{read_bytecode_from_file, read_inputs_from_file}; +use crate::errors::CliError; +use nargo::{foreign_calls::DefaultForeignCallBuilder, ops::execute_program}; + +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, + + /// Use pedantic ACVM solving, i.e. double-check some black-box function + /// assumptions when solving. + /// This is disabled by default. + #[clap(long, default_value = "false")] + pedantic_solving: 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, args.pedantic_solving)?; + 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], + pedantic_solving: bool, +) -> Result, CliError> { + let program: Program = Program::deserialize_program(bytecode) + .map_err(|_| CliError::CircuitDeserializationError())?; + execute_program( + &program, + inputs_map, + &Bn254BlackBoxSolver(pedantic_solving), + &mut DefaultForeignCallBuilder { + output: PrintOutput::Stdout, + enable_mocks: false, + ..Default::default() + } + .build(), + ) + .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..f31e123d0cd --- /dev/null +++ b/tooling/acvm_cli/src/cli/mod.rs @@ -0,0 +1,33 @@ +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), +} + +pub(crate) fn start_cli() -> eyre::Result<()> { + let ACVMCli { command } = ACVMCli::parse(); + + match command { + ACVMCommand::Execute(args) => execute_cmd::run(args), + }?; + + Ok(()) +} diff --git a/tooling/acvm_cli/src/errors.rs b/tooling/acvm_cli/src/errors.rs new file mode 100644 index 00000000000..886c1bf80f2 --- /dev/null +++ b/tooling/acvm_cli/src/errors.rs @@ -0,0 +1,50 @@ +use acir::FieldElement; +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/debugger/Cargo.toml b/tooling/debugger/Cargo.toml new file mode 100644 index 00000000000..b9b83d86836 --- /dev/null +++ b/tooling/debugger/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "noir_debugger" +description = "Debugger for Noir" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[lints] +workspace = true + +[build-dependencies] +build-data.workspace = true + +[dependencies] +acvm.workspace = true +fm.workspace = true +nargo.workspace = true +noirc_frontend = { workspace = true, features = ["bn254"] } +noirc_printable_type.workspace = true +noirc_errors.workspace = true +noirc_driver.workspace = true +noirc_artifacts.workspace = true +thiserror.workspace = true +codespan-reporting.workspace = true +dap.workspace = true +easy-repl = "0.2.1" +owo-colors = "3" +serde_json.workspace = true + +[dev-dependencies] +assert_cmd = "2.0.12" +rexpect = "0.5.0" +tempfile.workspace = true diff --git a/tooling/debugger/README.md b/tooling/debugger/README.md new file mode 100644 index 00000000000..0ec3b6f0cd4 --- /dev/null +++ b/tooling/debugger/README.md @@ -0,0 +1,428 @@ +# Noir Debugger + +There are currently two ways of debugging Noir programs, both in active development and in experimental phase: + +1. The REPL debugger, which currently ships with Nargo behind a feature flag. +2. The VS Code extension, which hasn't still reached minimum viability, and so must be manually set up. + +This README explains how to use each of them as well as specifying which features are currently mature and which ones are unstable. + +## Supported project types + +At the time of writing, the debugger supports debugging binary projects, but not contracts. At the end of this README, we'll elaborate on what the current state of Noir contract debugging is, and the pre-requisites to fulfil. + + +## REPL debugger + +In order to use the REPL debugger, you will need to install a new enough version of Nargo. At the time of writing, the nightly version is 0.20.0, so we'll base this guide on it. + +Let's debug a simple circuit: + +``` +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: + +`$ nargo debug` + +You should be seeing this in your terminal: + +``` +[main] Starting debugger +At opcode 0: EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] +At ~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> +``` + +The debugger displays the current opcode, and the corresponding Noir code location associated to it, and it is now waiting for us to drive it. + +Let's first take a look at the available commands. For that we'll use the `help` command. + +``` +At ~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> help +Available commands: + + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + memory show Brillig memory (valid when executing a + Brillig block) + into step into to the next opcode + next step until a new source location is reached + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + step step to the next ACIR opcode + registers show Brillig registers (valid when executing + a Brillig block) + regset index:usize value:String update a Brillig register with the given + value + restart restart the debugging session + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + continue continue execution until the end of the + program + opcodes display ACIR opcodes + memset index:usize value:String update a Brillig memory cell with the given + value + +Other commands: + + help Show this help message + quit Quit repl +``` + +The command menu is pretty self-explanatory. Some commands operate only at Brillig level, such as `memory`, `memset`, `registers`, `regset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing Brillig code: + +``` +> registers +Not executing a Brillig block +> +``` + +Before continuing, we can take a look at the initial witness map: + +``` +> witness +_1 = 1 +_2 = 2 +> +``` + +Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2: + +``` +> witness +_1 = 1 +_2 = 2 +> witness 2 3 +_2 = 3 +> witness +_1 = 1 +_2 = 3 +> witness 2 2 +_2 = 2 +> witness +_1 = 1 +_2 = 2 +> +``` + +Let's take a look at this circuit's ACIR, using the `opcodes` command: + +``` +> opcodes + 0 -> EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> +``` + +Note: in future versions of the debugger, we could explore prettier or more compact formats to print opcodes. + +So the next opcode will take us to Brillig execution. Let's step into opcode 1 so we can explore Brillig debugger commands. + +``` +> into +At opcode 1: BRILLIG: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] +outputs: [Simple(Witness(4))] +[JumpIfNot { condition: RegisterIndex(0), location: 3 }, Const { destination: RegisterIndex(1), value: Value { inner: 1 } }, BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) }, Stop] + +At /~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +``` + +In disassembly view: + +``` +> op + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 |-> JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> witness +_1 = 1 +_2 = 2 +_3 = 1 +> +``` + +We can see two arrow `->` cursors: one indicates where we are from the perspective of ACIR (opcode 1), and the other one shows us where we are in the context of the current Brillig block (opcode 1.0). + +Note: REPL commands are autocompleted when not ambiguous, so `opcodes` can be run just with `op`, `into` with `i`, etc. + +The next opcode to execute is a `JumpIfNot`, which reads from register 0. Let's inspect Brillig register state: + +``` +> op + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 |-> JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> registers +Brillig VM registers not available +``` + +Oops. This is unexpected, even though we were already in a Brillig block, we couldn't access the Brillig registers. This is a known issue: when just entering the Brillig block, the ACVM has not yet initialized the Brillig VM, so we can't introspect it. + +Note: In order to solve this, we would have to change the way the ACVM works, or add special handling for this case (after all, the debugger does know we're at the first opcode of a Brillig block and could keep track of how registers will be initialized). At the time of writing, we haven't yet solved this case. + +For now, let's just step once more: + +``` +> i +At opcode 1.1: Const { destination: RegisterIndex(1), value: Value { inner: 1 } } +> registers +0 = 1 +> +``` + +Now we can see that register 0 was initialized with a value of 1, so the `JumpIfNot` didn't activate. After executing opcode 1, we should see register 1 gets a value of 1: + +``` +> i +At opcode 1.2: BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } +> regist +0 = 1 +1 = 1 +> +``` + +The last operation will compute `Reg0 <- Reg1 / Reg0`: + +``` +> i +At opcode 1.3: Stop +> registers +0 = 1 +1 = 1 +> +``` + +Once we step again, we'll be out of Brillig and back on ACVM territory. With a new witness `_4` corresponding to the result of the Brillig block execution: + +``` +> op + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 -> EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> wit +_1 = 1 +_2 = 2 +_3 = 1 +_4 = 1 +> +``` + +At any time, we might also decide to restart from the beginning: + +``` +> restart +Restarted debugging session. +At opcode 0: EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] +At ~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> +``` + +Let's set a breakpoint. For that, we can use the opcode id's listed by the `opcodes` command: + +``` +> opcodes + 0 -> EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> break 1.2 +Added breakpoint at opcode 1.2 +``` + +Now we can have the debugger continue all the way to opcode 1.2: + +``` +> break 1.2 +Added breakpoint at opcode 1.2 +> continue +(Continuing execution...) +Stopped at breakpoint in opcode 1.2 +At opcode 1.2: BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } +> opcodes + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 |-> BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> +``` + +Let's continue to the end: + +``` +> continue +(Continuing execution...) +Finished execution +> q +[main] Circuit witness successfully solved +``` + +Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. + + +# Testing experimental features + +There's a number of features that are in active development and that can't yet be merged to the main branch for different reasons. In this section we detail what those features are and how to try them out. + +## Build from experimental branch at fork + +Build Nargo by pulling the source version from https://github.com/manastech/noir/tree/dap-with-vars. + +This will result in a Nargo binary being written to `PROJECT_ROOT/target/debug/nargo`. We will use this path later, so keep it at hand or export it to a an env var. For example: + +`export NARGO_EXP=PROJECT_ROOT/target/debug/nargo` + +## About the experimental features + +There are currently 2 experimental features in the debugger: + +- Variables inspection +- Stacktrace inspection + +NOTE: Supporting variables inspection requires extensive instrumentation of the compiler, handling all cases of variable creation, types, and value assignment. At the time of writing this README, some cases are still not supported. For example, if your program uses slices or references, this compiler version might panic when trying to compile them, or at some point during the debugger step-by-step execution. This is the main reason why this feature has not yet been merged into master. + +## Trying out REPL experimental features + +To try out these features, go through the same steps as described at the REPL Debugger section above, but instead of using `nargo debug` use `$NARGO_EXP debug` (assuming you exported your custom built Nargo binary to NARGO_EXP). + +When entering `help` on this version, you'll find two new commands: + +``` +... +stacktrace display the current stack trace +... +vars show variable values available at this point + in execution +``` + +Running `vars` will print the current variables in scope, and its current values: + +``` +At /mul_1/src/main.nr:6:5 + 1 // Test unsafe integer multiplication with overflow: 12^8 = 429 981 696 + 2 // The circuit should handle properly the growth of the bit size + 3 fn main(mut x: u32, y: u32, z: u32) { + 4 x *= y; + 5 x *= x; //144 + 6 -> x *= x; //20736 + 7 x *= x; //429 981 696 + 8 assert(x == z); + 9 } +> vars +y:UnsignedInteger { width: 32 }=Field(4), z:UnsignedInteger { width: 32 }=Field(2¹⁶×6561), x:UnsignedInteger { width: 32 }=Field(2⁴×9) +> +``` + +Running `stacktrace` will print information about the current frame in the stacktrace: + +``` +> stacktrace +Frame #0, opcode 12: EXPR [ (1, _5, _5) (-1, _6) 0 ] +At /1_mul/src/main.nr:6:5 + 1 // Test unsafe integer multiplication with overflow: 12^8 = 429 981 696 + 2 // The circuit should handle properly the growth of the bit size + 3 fn main(mut x: u32, y: u32, z: u32) { + 4 x *= y; + 5 x *= x; //144 + 6 -> x *= x; //20736 + 7 x *= x; //429 981 696 + 8 assert(x == z); + 9 } +> +``` + +## Testing the VS Code extension (experimental) + +There is a fork of the official Noir Visual Studio extension which enables the debugger in VS Code. This fork is at: https://github.com/manastech/vscode-noir/tree/dap-support. + +In this section, we'll explain how to test the VS Code Noir debugger combining that extension fork with the experimental features branch discussed above. + +1. First, get a copy of the extension source code from https://github.com/manastech/vscode-noir/tree/dap-support. + +2. Package the extension by running `npm run package`. + +3. Open the root folder of the extension on VS Code. + +4. From VS Code, press fn+F5. This will open a new VS Code window with the extension loaded from source. + +5. Go to Code -> Settings -> Extensions -> Noir Language Server. Look for the property `Nargo Path` and enter the path to the experimental build you got as a result of following the steps at [Trying out REPL experimental features](#trying-out-repl-experimental-features). + +6. At the VS Code sidebar, go to the debugger section (see screenshot). Click "Add configuration". Overwrite the `projectFolder` property with the absolute path to the Nargo project you want to debug. + +Screenshot 2023-12-18 at 14 37 38 + +7. Go to a Noir file you want to debug. Navigate again to the debug section of VS Code, and click the "play" icon. + +The debugger should now have started. Current features exposed to the debugger include different kinds of stepping interactions, variable inspection and stacktraces. At the time of writing, Brillig registers and memory are not being exposed, but they will soon be. + +![Screen Recording 2023-12-18 at 14 14 28](https://github.com/manastech/noir/assets/651693/36b4becb-953a-4158-9c5a-7a185673f54f) + +## Towards debugging contracts + +### Contracts Runtime + +The execution of Noir contracts depends on a foreign call execution runtime to resolve all the oracle calls that the contract functions depend on. + +This means for the debugger to be usable with contracts we need to be able to do at least one of the following: + +1. Let users mock out a foreign call executor, and run the debugger with it. +2. Instrument live environments, such as the Sandbox, so that calls and transactions can be driven by the debugger, which ultimately means the debugger would use the same foreign call executor a live Sandbox uses for normal execution of Noir circuits. + +Both of these scenarios imply making the debugger available to language runtimes external to Noir. The Sandbox/PXE runs on JS runtimes, and an hypothetical mockable foreign executor could be in principle written in any language. So it seems the most promising way forward is to make sure that the debugger itself is consumable in JS runtimes. + diff --git a/tooling/debugger/build.rs b/tooling/debugger/build.rs new file mode 100644 index 00000000000..63924de8336 --- /dev/null +++ b/tooling/debugger/build.rs @@ -0,0 +1,70 @@ +use std::collections::HashSet; +use std::fs::File; +use std::io::Write; +use std::path::{Path, PathBuf}; + +const GIT_COMMIT: &&str = &"GIT_COMMIT"; + +fn main() { + // 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(); + build_data::no_debug_rebuilds(); + } + + let out_dir = std::env::var("OUT_DIR").unwrap(); + let destination = Path::new(&out_dir).join("debug.rs"); + let mut test_file = File::create(destination).unwrap(); + + // Try to find the directory that Cargo sets when it is running; otherwise fallback to assuming the CWD + // is the root of the repository and append the crate path + let root_dir = match std::env::var("CARGO_MANIFEST_DIR") { + Ok(dir) => PathBuf::from(dir).parent().unwrap().parent().unwrap().to_path_buf(), + Err(_) => std::env::current_dir().unwrap(), + }; + let test_dir = root_dir.join("test_programs"); + + // Rebuild if the tests have changed + println!("cargo:rerun-if-changed=tests"); + println!("cargo:rerun-if-changed=ignored-tests.txt"); + println!("cargo:rerun-if-changed={}", test_dir.as_os_str().to_str().unwrap()); + + generate_debugger_tests(&mut test_file, &test_dir); +} + +fn generate_debugger_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); + + let test_case_dirs = + std::fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); + let ignored_tests_contents = std::fs::read_to_string("ignored-tests.txt").unwrap(); + let ignored_tests = ignored_tests_contents.lines().collect::>(); + + for test_dir in test_case_dirs { + let test_name = + test_dir.file_name().into_string().expect("Directory can't be converted to string"); + let ignored = ignored_tests.contains(test_name.as_str()); + 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] +{ignored} +fn debug_{test_name}() {{ + debugger_execution_success("{test_dir}"); +}} + "#, + test_dir = test_dir.display(), + ignored = if ignored { "#[ignore]" } else { "" }, + ) + .expect("Could not write templated test file."); + } +} diff --git a/tooling/debugger/ignored-tests.txt b/tooling/debugger/ignored-tests.txt new file mode 100644 index 00000000000..e0548fe1e1a --- /dev/null +++ b/tooling/debugger/ignored-tests.txt @@ -0,0 +1,9 @@ +brillig_references +debug_logs +is_unconstrained +macros +reference_counts +references +regression_4709 +reference_only_used_as_alias +brillig_rc_regression_6123 diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs new file mode 100644 index 00000000000..9741749df64 --- /dev/null +++ b/tooling/debugger/src/context.rs @@ -0,0 +1,1383 @@ +use crate::foreign_calls::DebugForeignCallExecutor; +use acvm::acir::brillig::BitSize; +use acvm::acir::circuit::brillig::{BrilligBytecode, BrilligFunctionId}; +use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; +use acvm::acir::native_types::{Witness, WitnessMap, WitnessStack}; +use acvm::brillig_vm::MemoryValue; +use acvm::pwg::{ + ACVMStatus, AcirCallWaitInfo, BrilligSolver, BrilligSolverStatus, ForeignCallWaitInfo, + OpcodeNotSolvable, StepResult, ACVM, +}; +use acvm::{BlackBoxFunctionSolver, FieldElement}; + +use codespan_reporting::files::{Files, SimpleFile}; +use fm::FileId; +use nargo::errors::{ExecutionError, Location}; +use nargo::NargoError; +use noirc_artifacts::debug::{DebugArtifact, StackFrame}; +use noirc_driver::DebugFile; + +use thiserror::Error; + +use std::collections::BTreeMap; +use std::collections::{hash_set::Iter, HashSet}; + +/// A Noir program is composed by +/// `n` ACIR circuits +/// |_ `m` ACIR opcodes +/// |_ Acir call +/// |_ Acir Brillig function invocation +/// |_ `p` Brillig opcodes +/// +/// The purpose of this structure is to map the opcode locations in ACIR circuits into +/// a flat contiguous address space to be able to expose them to the DAP interface. +/// In this address space, the ACIR circuits are laid out one after the other, and +/// Brillig functions called from such circuits are expanded inline, replacing +/// the `BrilligCall` ACIR opcode. +/// +/// `addresses: Vec>` +/// * The outer vec is `n` sized - one element per ACIR circuit +/// * Each nested vec is `m` sized - one element per ACIR opcode in circuit +/// * Each element is the "virtual address" of such opcode +/// +/// For flattening we map each ACIR circuit and ACIR opcode with a sequential address number +/// We start by assigning 0 to the very first ACIR opcode and then start accumulating by +/// traversing by depth-first +/// +/// Even if the address space is continuous, the `addresses` tree only +/// keeps track of the ACIR opcodes, since the Brillig opcode addresses can be +/// calculated from the initial opcode address. +/// As a result the flattened indexed addresses list may have "holes". +/// +/// If between two consequent `addresses` nodes there is a "hole" (an address jump), +/// this means that the first one is actually a ACIR Brillig call +/// which has as many brillig opcodes as `second_address - first_address` +/// +#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +pub struct AddressMap { + addresses: Vec>, + + /// Virtual address of the last opcode of the program + last_valid_address: usize, + + /// Maps the "holes" in the `addresses` nodes to the Brillig function ID + /// associated with that address space. + brillig_addresses: Vec, +} + +/// Associates a BrilligFunctionId with the address space. +/// A BrilligFunctionId is found by checking whether an address is between +/// the `start_address` and `end_address` +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +struct BrilligAddressSpace { + /// The start of the Brillig call address space + start_address: usize, + /// The end of the Brillig address space + end_address: usize, + /// The Brillig function id associated with this address space + brillig_function_id: BrilligFunctionId, +} + +impl AddressMap { + pub(super) fn new( + circuits: &[Circuit], + unconstrained_functions: &[BrilligBytecode], + ) -> Self { + let opcode_address_size = |opcode: &Opcode| { + if let Opcode::BrilligCall { id, .. } = opcode { + (unconstrained_functions[id.as_usize()].bytecode.len(), Some(*id)) + } else { + (1, None) + } + }; + + let mut addresses = Vec::with_capacity(circuits.len()); + let mut next_address = 0usize; + let mut brillig_addresses = Vec::new(); + + for circuit in circuits { + let mut circuit_addresses = Vec::with_capacity(circuit.opcodes.len()); + for opcode in &circuit.opcodes { + circuit_addresses.push(next_address); + let (address_size, brillig_function_id) = opcode_address_size(opcode); + if let Some(brillig_function_id) = brillig_function_id { + let brillig_address_space = BrilligAddressSpace { + start_address: next_address, + end_address: next_address + address_size, + brillig_function_id, + }; + brillig_addresses.push(brillig_address_space); + } + next_address += address_size; + } + addresses.push(circuit_addresses); + } + + Self { addresses, last_valid_address: next_address - 1, brillig_addresses } + } + + /// Returns the absolute address of the opcode at the given location. + /// Absolute here means accounting for nested Brillig opcodes in BrilligCall + /// opcodes. + pub fn debug_location_to_address(&self, location: &DebugLocation) -> usize { + let circuit_addresses = &self.addresses[location.circuit_id as usize]; + match &location.opcode_location { + OpcodeLocation::Acir(acir_index) => circuit_addresses[*acir_index], + OpcodeLocation::Brillig { acir_index, brillig_index } => { + circuit_addresses[*acir_index] + *brillig_index + } + } + } + + pub fn address_to_debug_location(&self, address: usize) -> Option { + if address > self.last_valid_address { + return None; + } + // We binary search if the given address is the first opcode address of each circuit id + // if is not, this means that the address itself is "contained" in the previous + // circuit indicated by `Err(insert_index)` + let circuit_id = + match self.addresses.binary_search_by(|addresses| addresses[0].cmp(&address)) { + Ok(found_index) => found_index, + // This means that the address is not in `insert_index` circuit + // because is an `Err`, so it must be included in previous circuit vec of opcodes + Err(insert_index) => insert_index - 1, + }; + + // We binary search among the selected `circuit_id`` list of opcodes + // If Err(insert_index) this means that the given address + // is a Brillig addresses that's contained in previous index ACIR opcode index + let (opcode_location, brillig_function_id) = + match self.addresses[circuit_id].binary_search(&address) { + Ok(found_index) => (OpcodeLocation::Acir(found_index), None), + Err(insert_index) => { + let acir_index = insert_index - 1; + let base_offset = self.addresses[circuit_id][acir_index]; + let brillig_index = address - base_offset; + let brillig_function_id = self + .brillig_addresses + .iter() + .find(|brillig_address_space| { + address >= brillig_address_space.start_address + && address <= brillig_address_space.end_address + }) + .map(|brillig_address_space| brillig_address_space.brillig_function_id); + (OpcodeLocation::Brillig { acir_index, brillig_index }, brillig_function_id) + } + }; + + Some(DebugLocation { circuit_id: circuit_id as u32, opcode_location, brillig_function_id }) + } +} + +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +pub struct DebugLocation { + pub circuit_id: u32, + pub opcode_location: OpcodeLocation, + pub brillig_function_id: Option, +} + +impl std::fmt::Display for DebugLocation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let circuit_id = self.circuit_id; + match self.opcode_location { + OpcodeLocation::Acir(index) => write!(f, "{circuit_id}:{index}"), + OpcodeLocation::Brillig { acir_index, brillig_index } => { + write!(f, "{circuit_id}:{acir_index}.{brillig_index}") + } + } + } +} + +#[derive(Error, Debug)] +pub enum DebugLocationFromStrError { + #[error("Invalid debug location string: {0}")] + InvalidDebugLocationString(String), +} + +impl std::str::FromStr for DebugLocation { + type Err = DebugLocationFromStrError; + fn from_str(s: &str) -> Result { + let parts: Vec<_> = s.split(':').collect(); + let error = Err(DebugLocationFromStrError::InvalidDebugLocationString(s.to_string())); + + match parts.len() { + 1 => OpcodeLocation::from_str(parts[0]).map_or(error, |opcode_location| { + Ok(DebugLocation { circuit_id: 0, opcode_location, brillig_function_id: None }) + }), + 2 => { + let first_part = parts[0].parse().ok(); + let second_part = OpcodeLocation::from_str(parts[1]).ok(); + if let (Some(circuit_id), Some(opcode_location)) = (first_part, second_part) { + Ok(DebugLocation { circuit_id, opcode_location, brillig_function_id: None }) + } else { + error + } + } + _ => error, + } + } +} + +#[derive(Debug)] +pub(super) enum DebugCommandResult { + Done, + Ok, + BreakpointReached(DebugLocation), + Error(NargoError), +} + +pub struct ExecutionFrame<'a, B: BlackBoxFunctionSolver> { + circuit_id: u32, + acvm: ACVM<'a, FieldElement, B>, +} + +pub(super) struct DebugContext<'a, B: BlackBoxFunctionSolver> { + pub(crate) acvm: ACVM<'a, FieldElement, B>, + current_circuit_id: u32, + brillig_solver: Option>, + + witness_stack: WitnessStack, + acvm_stack: Vec>, + + backend: &'a B, + foreign_call_executor: Box, + + debug_artifact: &'a DebugArtifact, + breakpoints: HashSet, + source_to_locations: BTreeMap>, + + circuits: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], + + acir_opcode_addresses: AddressMap, +} + +impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { + pub(super) fn new( + blackbox_solver: &'a B, + circuits: &'a [Circuit], + debug_artifact: &'a DebugArtifact, + 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 current_circuit_id: u32 = 0; + let initial_circuit = &circuits[current_circuit_id as usize]; + let acir_opcode_addresses = AddressMap::new(circuits, unconstrained_functions); + Self { + acvm: ACVM::new( + blackbox_solver, + &initial_circuit.opcodes, + initial_witness, + unconstrained_functions, + &initial_circuit.assert_messages, + ), + current_circuit_id, + brillig_solver: None, + witness_stack: WitnessStack::default(), + acvm_stack: vec![], + backend: blackbox_solver, + foreign_call_executor, + debug_artifact, + breakpoints: HashSet::new(), + source_to_locations: source_to_opcodes, + circuits, + unconstrained_functions, + acir_opcode_addresses, + } + } + + pub(super) fn get_opcodes(&self) -> &[Opcode] { + self.acvm.opcodes() + } + + pub(super) fn get_opcodes_of_circuit(&self, circuit_id: u32) -> &[Opcode] { + &self.circuits[circuit_id as usize].opcodes + } + + pub(super) fn get_witness_map(&self) -> &WitnessMap { + self.acvm.witness_map() + } + + pub(super) fn overwrite_witness( + &mut self, + witness: Witness, + value: FieldElement, + ) -> Option { + self.acvm.overwrite_witness(witness, value) + } + + pub(super) fn get_current_debug_location(&self) -> Option { + let ip = self.acvm.instruction_pointer(); + if ip >= self.get_opcodes().len() { + None + } else { + let (opcode_location, brillig_function_id) = + if let Some(ref solver) = self.brillig_solver { + let function_id = solver.function_id; + ( + OpcodeLocation::Brillig { + acir_index: ip, + brillig_index: solver.program_counter(), + }, + Some(function_id), + ) + } else { + (OpcodeLocation::Acir(ip), None) + }; + Some(DebugLocation { + circuit_id: self.current_circuit_id, + brillig_function_id, + opcode_location, + }) + } + } + + pub(super) fn get_call_stack(&self) -> Vec { + // Build the frames from parent ACIR calls + let mut frames: Vec<_> = self + .acvm_stack + .iter() + .map(|ExecutionFrame { circuit_id, acvm }| DebugLocation { + circuit_id: *circuit_id, + opcode_location: OpcodeLocation::Acir(acvm.instruction_pointer()), + brillig_function_id: None, + }) + .collect(); + + // Now add the frame(s) for the currently executing ACVM + let instruction_pointer = self.acvm.instruction_pointer(); + let circuit_id = self.current_circuit_id; + if let Some(ref solver) = self.brillig_solver { + frames.extend(solver.get_call_stack().iter().map(|program_counter| DebugLocation { + circuit_id, + opcode_location: OpcodeLocation::Brillig { + acir_index: instruction_pointer, + brillig_index: *program_counter, + }, + brillig_function_id: Some(solver.function_id), + })); + } else if instruction_pointer < self.get_opcodes().len() { + frames.push(DebugLocation { + circuit_id, + opcode_location: OpcodeLocation::Acir(instruction_pointer), + brillig_function_id: None, + }); + } + frames + } + + pub(super) fn is_source_location_in_debug_module(&self, location: &Location) -> bool { + self.debug_artifact + .file_map + .get(&location.file) + .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_locations.get(file_id)?; + let found_location = 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_location) + } + + /// Returns the callstack in source code locations for the currently + /// executing opcode. This can be `None` if the execution finished (and + /// `get_current_opcode_location()` returns `None`) or if the opcode is not + /// mapped to a specific source location in the debug artifact (which can + /// happen for certain opcodes inserted synthetically by the compiler). + /// This function also filters source locations that are determined to be in + /// the internal debug module. + pub(super) fn get_current_source_location(&self) -> Option> { + self.get_current_debug_location() + .as_ref() + .map(|debug_location| self.get_source_location_for_debug_location(debug_location)) + .filter(|v: &Vec| !v.is_empty()) + } + + /// Returns the (possible) stack of source locations corresponding to the + /// given opcode location. Due to compiler inlining it's possible for this + /// function to return multiple source locations. An empty vector means that + /// the given opcode location cannot be mapped back to a source location + /// (eg. it may be pure debug instrumentation code or other synthetically + /// produced opcode by the compiler) + pub(super) fn get_source_location_for_debug_location( + &self, + debug_location: &DebugLocation, + ) -> Vec { + self.debug_artifact.debug_symbols[debug_location.circuit_id as usize] + .opcode_location(&debug_location.opcode_location) + .unwrap_or_else(|| { + if let (Some(brillig_function_id), Some(brillig_location)) = ( + debug_location.brillig_function_id, + debug_location.opcode_location.to_brillig_location(), + ) { + let brillig_locations = self.debug_artifact.debug_symbols + [debug_location.circuit_id as usize] + .brillig_locations + .get(&brillig_function_id); + brillig_locations.unwrap().get(&brillig_location).cloned().unwrap_or_default() + } else { + vec![] + } + }) + .into_iter() + .filter(|source_location| !self.is_source_location_in_debug_module(source_location)) + .collect() + } + + /// Returns the current call stack with expanded source locations. In + /// general, the matching between opcode location and source location is 1 + /// to 1, but due to the compiler inlining functions a single opcode + /// location may expand to multiple source locations. + pub(super) fn get_source_call_stack(&self) -> Vec<(DebugLocation, Location)> { + self.get_call_stack() + .iter() + .flat_map(|debug_location| { + self.get_source_location_for_debug_location(debug_location) + .into_iter() + .map(|source_location| (*debug_location, source_location)) + }) + .collect() + } + + /// Returns the absolute address of the opcode at the given location. + pub fn debug_location_to_address(&self, location: &DebugLocation) -> usize { + self.acir_opcode_addresses.debug_location_to_address(location) + } + + // Returns the DebugLocation associated to the given address + pub fn address_to_debug_location(&self, address: usize) -> Option { + self.acir_opcode_addresses.address_to_debug_location(address) + } + + pub(super) fn render_opcode_at_location(&self, location: &DebugLocation) -> String { + let opcodes = self.get_opcodes_of_circuit(location.circuit_id); + match &location.opcode_location { + OpcodeLocation::Acir(acir_index) => { + let opcode = &opcodes[*acir_index]; + match opcode { + Opcode::BrilligCall { id, .. } => { + let first_opcode = &self.unconstrained_functions[id.as_usize()].bytecode[0]; + format!("BRILLIG {first_opcode:?}") + } + _ => format!("{opcode:?}"), + } + } + 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:?}") + } + _ => String::from(" | invalid"), + }, + } + } + + fn step_brillig_opcode(&mut self) -> DebugCommandResult { + let Some(mut solver) = self.brillig_solver.take() else { + unreachable!("Missing Brillig solver"); + }; + match solver.step() { + Ok(BrilligSolverStatus::InProgress) => { + self.brillig_solver = Some(solver); + if self.breakpoint_reached() { + DebugCommandResult::BreakpointReached( + self.get_current_debug_location() + .expect("Breakpoint reached but we have no location"), + ) + } else { + DebugCommandResult::Ok + } + } + Ok(BrilligSolverStatus::Finished) => { + let status = self.acvm.finish_brillig_with_solver(solver); + self.handle_acvm_status(status) + } + Ok(BrilligSolverStatus::ForeignCallWait(foreign_call)) => { + self.brillig_solver = Some(solver); + self.handle_foreign_call(foreign_call) + } + Err(err) => DebugCommandResult::Error(NargoError::ExecutionError( + ExecutionError::SolvingError(err, None), + )), + } + } + + 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) => { + if let Some(mut solver) = self.brillig_solver.take() { + solver.resolve_pending_foreign_call(foreign_call_result); + self.brillig_solver = Some(solver); + } else { + self.acvm.resolve_pending_foreign_call(foreign_call_result); + } + // TODO: should we retry executing the opcode somehow in this + // case? Otherwise, executing a foreign call takes two debugging + // steps. + DebugCommandResult::Ok + } + Err(error) => DebugCommandResult::Error(error.into()), + } + } + + fn handle_acir_call( + &mut self, + call_info: AcirCallWaitInfo, + ) -> DebugCommandResult { + let callee_circuit = &self.circuits[call_info.id.as_usize()]; + let callee_witness_map = call_info.initial_witness; + let callee_acvm = ACVM::new( + self.backend, + &callee_circuit.opcodes, + callee_witness_map, + self.unconstrained_functions, + &callee_circuit.assert_messages, + ); + let caller_acvm = std::mem::replace(&mut self.acvm, callee_acvm); + self.acvm_stack + .push(ExecutionFrame { circuit_id: self.current_circuit_id, acvm: caller_acvm }); + self.current_circuit_id = call_info.id.0; + + // Explicitly handling the new ACVM status here handles two edge cases: + // 1. there is a breakpoint set at the beginning of a circuit + // 2. the called circuit has no opcodes + self.handle_acvm_status(self.acvm.get_status().clone()) + } + + fn handle_acir_call_finished(&mut self) -> DebugCommandResult { + let caller_frame = self.acvm_stack.pop().expect("Execution stack should not be empty"); + let caller_acvm = caller_frame.acvm; + let callee_acvm = std::mem::replace(&mut self.acvm, caller_acvm); + self.current_circuit_id = caller_frame.circuit_id; + let call_solved_witness = callee_acvm.finalize(); + + let ACVMStatus::RequiresAcirCall(call_info) = self.acvm.get_status() else { + unreachable!("Resolving an ACIR call, the caller is in an invalid state"); + }; + let acir_to_call = &self.circuits[call_info.id.as_usize()]; + + 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 DebugCommandResult::Error( + 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(), + ); + } + } + self.acvm.resolve_pending_acir_call(call_resolved_outputs); + + DebugCommandResult::Ok + } + + fn handle_acvm_status(&mut self, status: ACVMStatus) -> DebugCommandResult { + match status { + ACVMStatus::Solved => { + if self.acvm_stack.is_empty() { + return DebugCommandResult::Done; + } + self.handle_acir_call_finished() + } + ACVMStatus::InProgress => { + if self.breakpoint_reached() { + DebugCommandResult::BreakpointReached( + self.get_current_debug_location() + .expect("Breakpoint reached but we have no location"), + ) + } else { + DebugCommandResult::Ok + } + } + ACVMStatus::Failure(error) => DebugCommandResult::Error(NargoError::ExecutionError( + ExecutionError::SolvingError(error, None), + )), + ACVMStatus::RequiresForeignCall(foreign_call) => self.handle_foreign_call(foreign_call), + ACVMStatus::RequiresAcirCall(call_info) => self.handle_acir_call(call_info), + } + } + + pub(super) fn step_into_opcode(&mut self) -> DebugCommandResult { + if self.brillig_solver.is_some() { + return self.step_brillig_opcode(); + } + + match self.acvm.step_into_brillig() { + StepResult::IntoBrillig(solver) => { + self.brillig_solver = Some(solver); + self.step_brillig_opcode() + } + StepResult::Status(status) => self.handle_acvm_status(status), + } + } + + fn get_current_acir_index(&self) -> Option { + self.get_current_debug_location().map(|debug_location| { + match debug_location.opcode_location { + OpcodeLocation::Acir(acir_index) | OpcodeLocation::Brillig { acir_index, .. } => { + acir_index + } + } + }) + } + + fn step_out_of_brillig_opcode(&mut self) -> DebugCommandResult { + let Some(start_acir_index) = self.get_current_acir_index() else { + return DebugCommandResult::Done; + }; + loop { + let result = self.step_into_opcode(); + if !matches!(result, DebugCommandResult::Ok) { + return result; + } + let new_acir_index = self.get_current_acir_index().unwrap(); + if new_acir_index != start_acir_index { + return DebugCommandResult::Ok; + } + } + } + + pub(super) fn is_executing_brillig(&self) -> bool { + if self.brillig_solver.is_some() { + return true; + } + + match self.get_current_debug_location() { + Some(DebugLocation { opcode_location: OpcodeLocation::Brillig { .. }, .. }) => true, + Some(DebugLocation { + circuit_id, + opcode_location: OpcodeLocation::Acir(acir_index), + .. + }) => { + matches!( + self.get_opcodes_of_circuit(circuit_id)[acir_index], + Opcode::BrilligCall { .. } + ) + } + _ => false, + } + } + + pub(super) fn step_acir_opcode(&mut self) -> DebugCommandResult { + if self.is_executing_brillig() { + self.step_out_of_brillig_opcode() + } else { + let status = self.acvm.solve_opcode(); + self.handle_acvm_status(status) + } + } + + /// Steps debugging execution until the next source location + pub(super) fn next_into(&mut self) -> DebugCommandResult { + let start_location = self.get_current_source_location(); + loop { + let result = self.step_into_opcode(); + if !matches!(result, DebugCommandResult::Ok) { + return result; + } + let new_location = self.get_current_source_location(); + if new_location.is_some() && new_location != start_location { + return DebugCommandResult::Ok; + } + } + } + + /// Steps debugging execution until the next source location at the same (or + /// less) call stack depth (eg. don't dive into function calls) + pub(super) fn next_over(&mut self) -> DebugCommandResult { + let start_call_stack = self.get_source_call_stack(); + loop { + let result = self.next_into(); + if !matches!(result, DebugCommandResult::Ok) { + return result; + } + let new_call_stack = self.get_source_call_stack(); + if new_call_stack.len() <= start_call_stack.len() { + return DebugCommandResult::Ok; + } + } + } + + /// Steps debugging execution until the next source location with a smaller + /// call stack depth (eg. returning from the current function) + pub(super) fn next_out(&mut self) -> DebugCommandResult { + let start_call_stack = self.get_source_call_stack(); + loop { + let result = self.next_into(); + if !matches!(result, DebugCommandResult::Ok) { + return result; + } + let new_call_stack = self.get_source_call_stack(); + if new_call_stack.len() < start_call_stack.len() { + return DebugCommandResult::Ok; + } + } + } + + pub(super) fn cont(&mut self) -> DebugCommandResult { + loop { + let result = self.step_into_opcode(); + if !matches!(result, DebugCommandResult::Ok) { + return result; + } + } + } + + pub(super) fn 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, + bit_size: BitSize, + ) { + if let Some(solver) = self.brillig_solver.as_mut() { + 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> { + 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_debug_location() { + self.breakpoints.contains(&location) + } else { + false + } + } + + pub(super) fn is_valid_debug_location(&self, location: &DebugLocation) -> bool { + if location.circuit_id as usize >= self.circuits.len() { + return false; + } + let opcodes = self.get_opcodes_of_circuit(location.circuit_id); + match location.opcode_location { + OpcodeLocation::Acir(acir_index) => acir_index < opcodes.len(), + OpcodeLocation::Brillig { acir_index, brillig_index } => { + 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 + } + } + } + } + + pub(super) fn is_breakpoint_set(&self, location: &DebugLocation) -> bool { + self.breakpoints.contains(location) + } + + pub(super) fn add_breakpoint(&mut self, location: DebugLocation) -> bool { + self.breakpoints.insert(location) + } + + pub(super) fn delete_breakpoint(&mut self, location: &DebugLocation) -> bool { + self.breakpoints.remove(location) + } + + pub(super) fn iterate_breakpoints(&self) -> Iter<'_, DebugLocation> { + self.breakpoints.iter() + } + + pub(super) fn clear_breakpoints(&mut self) { + self.breakpoints.clear(); + } + + pub(super) fn is_solved(&self) -> bool { + matches!(self.acvm.get_status(), ACVMStatus::Solved) + } + + pub fn finalize(mut self) -> WitnessStack { + let last_witness_map = self.acvm.finalize(); + self.witness_stack.push(0, last_witness_map); + self.witness_stack + } +} + +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 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(); + + for (circuit_id, debug_symbols) in debug_artifact.debug_symbols.iter().enumerate() { + add_opcode_locations_map( + &debug_symbols.locations, + &mut result, + &simple_files, + circuit_id, + None, + ); + + for (brillig_function_id, brillig_locations_map) in &debug_symbols.brillig_locations { + let brillig_locations_map = brillig_locations_map + .iter() + .map(|(key, val)| { + ( + // TODO: this is a temporary placeholder until the debugger is updated to handle the new brillig debug locations. + OpcodeLocation::Brillig { acir_index: 0, brillig_index: key.0 }, + val.clone(), + ) + }) + .collect(); + + add_opcode_locations_map( + &brillig_locations_map, + &mut result, + &simple_files, + circuit_id, + Some(*brillig_function_id), + ); + } + } + result.iter_mut().for_each(|(_, file_locations)| file_locations.sort_by_key(|x| (x.0, x.1))); + + result +} + +fn add_opcode_locations_map( + opcode_to_locations: &BTreeMap>, + source_to_locations: &mut BTreeMap>, + simple_files: &BTreeMap<&FileId, SimpleFile<&str, &str>>, + circuit_id: usize, + brillig_function_id: Option, +) { + for (opcode_location, source_locations) in opcode_to_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; + + let debug_location = DebugLocation { + circuit_id: circuit_id as u32, + opcode_location: *opcode_location, + brillig_function_id, + }; + source_to_locations.entry(file_id).or_default().push((line_number, debug_location)); + }); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::foreign_calls::DefaultDebugForeignCallExecutor; + use acvm::{ + acir::{ + brillig::{HeapVector, IntegerBitSize}, + circuit::{ + brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, + opcodes::{AcirFunctionId, BlockId, BlockType}, + }, + native_types::Expression, + AcirField, + }, + blackbox_solver::StubbedBlackBoxSolver, + brillig_vm::brillig::{ + BinaryFieldOp, HeapValueType, MemoryAddress, Opcode as BrilligOpcode, ValueOrArray, + }, + }; + use nargo::PrintOutput; + + #[test] + fn test_resolve_foreign_calls_stepping_into_brillig() { + let solver = StubbedBlackBoxSolver::default(); + let fe_1 = FieldElement::one(); + let w_x = Witness(1); + + let brillig_bytecode = BrilligBytecode { + bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress::direct(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(1u64), + }, + BrilligOpcode::Const { + destination: MemoryAddress::direct(2), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(1), + offset_address: MemoryAddress::direct(2), + }, + BrilligOpcode::ForeignCall { + function: "clear_mock".into(), + destinations: vec![], + destination_value_types: vec![], + inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], + input_value_types: vec![HeapValueType::field()], + }, + BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(2), + size: MemoryAddress::direct(2), + }, + }, + ], + }; + let opcodes = vec![Opcode::BrilligCall { + id: BrilligFunctionId(0), + inputs: vec![BrilligInputs::Single(Expression { + linear_combinations: vec![(fe_1, w_x)], + ..Expression::default() + })], + outputs: vec![], + predicate: None, + }]; + let brillig_funcs = &[brillig_bytecode]; + let current_witness_index = 2; + let circuit = Circuit { current_witness_index, opcodes, ..Circuit::default() }; + let circuits = &[circuit]; + + let debug_symbols = vec![]; + let file_map = BTreeMap::new(); + let debug_artifact = &DebugArtifact { debug_symbols, file_map }; + + let initial_witness = BTreeMap::from([(Witness(1), fe_1)]).into(); + + let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact( + PrintOutput::Stdout, + debug_artifact, + )); + let mut context = DebugContext::new( + &solver, + circuits, + debug_artifact, + initial_witness, + foreign_call_executor, + brillig_funcs, + ); + + assert_eq!( + context.get_current_debug_location(), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Acir(0), + brillig_function_id: None, + }) + ); + + // Const + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_debug_location(), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }) + ); + + // Const + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_debug_location(), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }) + ); + + // Calldatacopy + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_debug_location(), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }) + ); + + // try to execute the Brillig opcode (and resolve the foreign call) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_debug_location(), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }) + ); + + // retry the Brillig opcode (foreign call should be finished) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_debug_location(), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }) + ); + + // last Brillig opcode + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Done)); + assert_eq!(context.get_current_debug_location(), None); + } + + #[test] + fn test_break_brillig_block_while_stepping_acir_opcodes() { + let solver = StubbedBlackBoxSolver::default(); + let fe_0 = FieldElement::zero(); + let fe_1 = FieldElement::one(); + let w_x = Witness(1); + let w_y = Witness(2); + let w_z = Witness(3); + + let zero_usize = MemoryAddress::direct(2); + let one_usize = MemoryAddress::direct(3); + + // This Brillig block is equivalent to: z = x + y + let brillig_bytecode = BrilligBytecode { + bytecode: vec![ + BrilligOpcode::Const { + destination: MemoryAddress::direct(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(2u64), + }, + BrilligOpcode::Const { + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: one_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(1u64), + }, + BrilligOpcode::CalldataCopy { + destination_address: MemoryAddress::direct(0), + size_address: MemoryAddress::direct(0), + offset_address: zero_usize, + }, + BrilligOpcode::BinaryFieldOp { + destination: MemoryAddress::direct(0), + op: BinaryFieldOp::Add, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, + ], + }; + let opcodes = vec![ + // z = x + y + Opcode::BrilligCall { + id: BrilligFunctionId(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![], + linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], + q_c: fe_0, + }), + ]; + let current_witness_index = 3; + let circuit = Circuit { current_witness_index, opcodes, ..Circuit::default() }; + let circuits = &[circuit]; + + let debug_symbols = vec![]; + let file_map = BTreeMap::new(); + 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( + PrintOutput::Stdout, + debug_artifact, + )); + let brillig_funcs = &[brillig_bytecode]; + let mut context = DebugContext::new( + &solver, + circuits, + debug_artifact, + initial_witness, + foreign_call_executor, + brillig_funcs, + ); + + // set breakpoint + let breakpoint_location = DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }; + assert!(context.add_breakpoint(breakpoint_location)); + + // execute the first ACIR opcode (Brillig block) -> should reach the breakpoint instead + let result = context.step_acir_opcode(); + assert!(matches!(result, DebugCommandResult::BreakpointReached(_))); + assert_eq!(context.get_current_debug_location(), Some(breakpoint_location)); + + // continue execution to the next ACIR opcode + let result = context.step_acir_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_debug_location(), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Acir(1), + brillig_function_id: None + }) + ); + + // last ACIR opcode + let result = context.step_acir_opcode(); + assert!(matches!(result, DebugCommandResult::Done)); + assert_eq!(context.get_current_debug_location(), None); + } + + #[test] + fn test_address_debug_location_mapping() { + let solver = StubbedBlackBoxSolver::default(); + let brillig_one = + BrilligBytecode { bytecode: vec![BrilligOpcode::Return, BrilligOpcode::Return] }; + let brillig_two = BrilligBytecode { + bytecode: vec![BrilligOpcode::Return, BrilligOpcode::Return, BrilligOpcode::Return], + }; + + let circuit_one = Circuit { + opcodes: vec![ + Opcode::MemoryInit { + block_id: BlockId(0), + init: vec![], + block_type: BlockType::Memory, + }, + Opcode::BrilligCall { + id: BrilligFunctionId(0), + inputs: vec![], + outputs: vec![], + predicate: None, + }, + Opcode::Call { + id: AcirFunctionId(1), + inputs: vec![], + outputs: vec![], + predicate: None, + }, + Opcode::AssertZero(Expression::default()), + ], + ..Circuit::default() + }; + let circuit_two = Circuit { + opcodes: vec![ + Opcode::BrilligCall { + id: BrilligFunctionId(1), + inputs: vec![], + outputs: vec![], + predicate: None, + }, + Opcode::AssertZero(Expression::default()), + ], + ..Circuit::default() + }; + let circuits = vec![circuit_one, circuit_two]; + let debug_artifact = DebugArtifact { debug_symbols: vec![], file_map: BTreeMap::new() }; + let brillig_funcs = &[brillig_one, brillig_two]; + + let context = DebugContext::new( + &solver, + &circuits, + &debug_artifact, + WitnessMap::new(), + Box::new(DefaultDebugForeignCallExecutor::new(PrintOutput::Stdout)), + brillig_funcs, + ); + + let locations = + (0..=8).map(|address| context.address_to_debug_location(address)).collect::>(); + + // mapping from addresses to opcode locations + assert_eq!( + locations, + vec![ + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Acir(0), + brillig_function_id: None + }), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Acir(1), + brillig_function_id: None + }), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 1, brillig_index: 1 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Acir(2), + brillig_function_id: None + }), + Some(DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Acir(3), + brillig_function_id: None + }), + Some(DebugLocation { + circuit_id: 1, + opcode_location: OpcodeLocation::Acir(0), + brillig_function_id: None + }), + Some(DebugLocation { + circuit_id: 1, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }, + brillig_function_id: Some(BrilligFunctionId(1)), + }), + Some(DebugLocation { + circuit_id: 1, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }, + brillig_function_id: Some(BrilligFunctionId(1)), + }), + Some(DebugLocation { + circuit_id: 1, + opcode_location: OpcodeLocation::Acir(1), + brillig_function_id: None + }), + ] + ); + + let addresses = locations + .iter() + .flatten() + .map(|location| context.debug_location_to_address(location)) + .collect::>(); + + // and vice-versa + assert_eq!(addresses, (0..=8).collect::>()); + + // check edge cases + assert_eq!(None, context.address_to_debug_location(9)); + assert_eq!( + 1, + context.debug_location_to_address(&DebugLocation { + circuit_id: 0, + opcode_location: OpcodeLocation::Brillig { acir_index: 1, brillig_index: 0 }, + brillig_function_id: Some(BrilligFunctionId(0)), + }) + ); + assert_eq!( + 5, + context.debug_location_to_address(&DebugLocation { + circuit_id: 1, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 0 }, + brillig_function_id: Some(BrilligFunctionId(1)), + }) + ); + } +} diff --git a/tooling/debugger/src/dap.rs b/tooling/debugger/src/dap.rs new file mode 100644 index 00000000000..0d2095954e0 --- /dev/null +++ b/tooling/debugger/src/dap.rs @@ -0,0 +1,626 @@ +use std::collections::BTreeMap; +use std::io::{Read, Write}; + +use acvm::acir::circuit::brillig::BrilligBytecode; +use acvm::acir::circuit::Circuit; +use acvm::acir::native_types::WitnessMap; +use acvm::{BlackBoxFunctionSolver, FieldElement}; +use nargo::PrintOutput; + +use crate::context::DebugContext; +use crate::context::{DebugCommandResult, DebugLocation}; +use crate::foreign_calls::DefaultDebugForeignCallExecutor; + +use dap::errors::ServerError; +use dap::events::StoppedEventBody; +use dap::prelude::Event; +use dap::requests::{Command, Request, SetBreakpointsArguments}; +use dap::responses::{ + ContinueResponse, DisassembleResponse, ResponseBody, ScopesResponse, SetBreakpointsResponse, + SetExceptionBreakpointsResponse, SetInstructionBreakpointsResponse, StackTraceResponse, + ThreadsResponse, VariablesResponse, +}; +use dap::server::Server; +use dap::types::{ + Breakpoint, DisassembledInstruction, Scope, Source, StackFrame, SteppingGranularity, + StoppedEventReason, Thread, Variable, +}; +use noirc_artifacts::debug::DebugArtifact; + +use fm::FileId; +use noirc_driver::CompiledProgram; + +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, + next_breakpoint_id: BreakpointId, + instruction_breakpoints: Vec<(DebugLocation, BreakpointId)>, + source_breakpoints: BTreeMap>, +} + +enum ScopeReferences { + Locals = 1, + WitnessMap = 2, + InvalidScope = 0, +} + +impl From for ScopeReferences { + fn from(value: i64) -> Self { + match value { + 1 => Self::Locals, + 2 => Self::WitnessMap, + _ => Self::InvalidScope, + } + } +} + +impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { + pub fn new( + server: Server, + solver: &'a B, + circuits: &'a [Circuit], + debug_artifact: &'a DebugArtifact, + initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], + ) -> Self { + let context = DebugContext::new( + solver, + circuits, + debug_artifact, + initial_witness, + Box::new(DefaultDebugForeignCallExecutor::from_artifact( + PrintOutput::Stdout, + debug_artifact, + )), + unconstrained_functions, + ); + Self { + server, + context, + debug_artifact, + running: false, + next_breakpoint_id: 1, + instruction_breakpoints: vec![], + source_breakpoints: BTreeMap::new(), + } + } + + fn send_stopped_event(&mut self, reason: StoppedEventReason) -> Result<(), ServerError> { + let description = format!("{:?}", &reason); + self.server.send_event(Event::Stopped(StoppedEventBody { + reason, + description: Some(description), + thread_id: Some(0), + preserve_focus_hint: Some(false), + text: None, + all_threads_stopped: Some(false), + hit_breakpoint_ids: None, + }))?; + Ok(()) + } + + pub fn run_loop(&mut self) -> Result<(), ServerError> { + self.running = self.context.get_current_debug_location().is_some(); + + if self.running && self.context.get_current_source_location().is_none() { + // TODO: remove this? This is to ensure that the tool has a proper + // source location to show when first starting the debugger, but + // maybe the default behavior should be to start executing until the + // first breakpoint set. + _ = self.context.next_into(); + } + + self.server.send_event(Event::Initialized)?; + self.send_stopped_event(StoppedEventReason::Entry)?; + + while self.running { + let req = match self.server.poll_request()? { + Some(req) => req, + None => break, + }; + match req.command { + Command::Disconnect(_) => { + eprintln!("INFO: ending debugging session"); + self.server.respond(req.ack()?)?; + break; + } + Command::SetBreakpoints(_) => { + self.handle_set_source_breakpoints(req)?; + } + Command::SetExceptionBreakpoints(_) => { + self.server.respond(req.success(ResponseBody::SetExceptionBreakpoints( + SetExceptionBreakpointsResponse { breakpoints: None }, + )))?; + } + Command::SetInstructionBreakpoints(_) => { + self.handle_set_instruction_breakpoints(req)?; + } + Command::Threads => { + self.server.respond(req.success(ResponseBody::Threads(ThreadsResponse { + threads: vec![Thread { id: 0, name: "main".to_string() }], + })))?; + } + Command::StackTrace(_) => { + self.handle_stack_trace(req)?; + } + Command::Disassemble(_) => { + self.handle_disassemble(req)?; + } + Command::StepIn(ref args) => { + let granularity = + args.granularity.as_ref().unwrap_or(&SteppingGranularity::Statement); + match granularity { + SteppingGranularity::Instruction => self.handle_step(req)?, + _ => self.handle_next_into(req)?, + } + } + Command::StepOut(ref args) => { + let granularity = + args.granularity.as_ref().unwrap_or(&SteppingGranularity::Statement); + match granularity { + SteppingGranularity::Instruction => self.handle_step(req)?, + _ => self.handle_next_out(req)?, + } + } + Command::Next(ref args) => { + let granularity = + args.granularity.as_ref().unwrap_or(&SteppingGranularity::Statement); + match granularity { + SteppingGranularity::Instruction => self.handle_step(req)?, + _ => self.handle_next_over(req)?, + } + } + Command::Continue(_) => { + self.handle_continue(req)?; + } + Command::Scopes(_) => { + self.handle_scopes(req)?; + } + Command::Variables(ref _args) => { + self.handle_variables(req)?; + } + _ => { + eprintln!("ERROR: unhandled command: {:?}", req.command); + } + } + } + Ok(()) + } + + fn build_stack_trace(&self) -> Vec { + let stack_frames = self.context.get_variables(); + + self.context + .get_source_call_stack() + .iter() + .enumerate() + .map(|(index, (debug_location, source_location))| { + let line_number = + 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.debug_location_to_address(debug_location); + + StackFrame { + id: index as i64, + name, + source: Some(Source { + path: self.debug_artifact.file_map[&source_location.file] + .path + .to_str() + .map(String::from), + ..Source::default() + }), + line: line_number as i64, + column: column_number as i64, + instruction_pointer_reference: Some(address.to_string()), + ..StackFrame::default() + } + }) + .rev() + .collect() + } + + fn handle_stack_trace(&mut self, req: Request) -> Result<(), ServerError> { + let frames = self.build_stack_trace(); + let total_frames = Some(frames.len() as i64); + self.server.respond(req.success(ResponseBody::StackTrace(StackTraceResponse { + stack_frames: frames, + total_frames, + })))?; + Ok(()) + } + + fn handle_disassemble(&mut self, req: Request) -> Result<(), ServerError> { + let Command::Disassemble(ref args) = req.command else { + unreachable!("handle_disassemble called on a non disassemble request"); + }; + + // 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 address = starting_address + instruction_offset; + let mut count = args.instruction_count; + + let mut instructions: Vec = vec![]; + + while count > 0 { + let debug_location = if address >= 0 { + self.context.address_to_debug_location(address as usize) + } else { + None + }; + + if let Some(debug_location) = debug_location { + instructions.push(DisassembledInstruction { + address: address.to_string(), + // we'll use the instruction_bytes field to render the OpcodeLocation + instruction_bytes: Some(debug_location.to_string()), + instruction: self.context.render_opcode_at_location(&debug_location), + ..DisassembledInstruction::default() + }); + } else { + // entry for invalid location to fill up the request + instructions.push(DisassembledInstruction { + address: "---".to_owned(), + instruction: "---".to_owned(), + ..DisassembledInstruction::default() + }); + } + count -= 1; + address += 1; + } + + self.server.respond( + req.success(ResponseBody::Disassemble(DisassembleResponse { instructions })), + )?; + Ok(()) + } + + fn handle_step(&mut self, req: Request) -> Result<(), ServerError> { + let result = self.context.step_into_opcode(); + eprintln!("INFO: stepped by instruction with result {result:?}"); + self.server.respond(req.ack()?)?; + self.handle_execution_result(result) + } + + fn handle_next_into(&mut self, req: Request) -> Result<(), ServerError> { + let result = self.context.next_into(); + eprintln!("INFO: stepped into by statement with result {result:?}"); + self.server.respond(req.ack()?)?; + self.handle_execution_result(result) + } + + fn handle_next_out(&mut self, req: Request) -> Result<(), ServerError> { + let result = self.context.next_out(); + eprintln!("INFO: stepped out by statement with result {result:?}"); + self.server.respond(req.ack()?)?; + self.handle_execution_result(result) + } + + fn handle_next_over(&mut self, req: Request) -> Result<(), ServerError> { + let result = self.context.next_over(); + eprintln!("INFO: stepped over by statement with result {result:?}"); + self.server.respond(req.ack()?)?; + self.handle_execution_result(result) + } + + fn handle_continue(&mut self, req: Request) -> Result<(), ServerError> { + let result = self.context.cont(); + eprintln!("INFO: continue with result {result:?}"); + self.server.respond(req.success(ResponseBody::Continue(ContinueResponse { + all_threads_continued: Some(true), + })))?; + self.handle_execution_result(result) + } + + fn find_breakpoints_at_location(&self, debug_location: &DebugLocation) -> Vec { + let mut result = vec![]; + for (location, id) in &self.instruction_breakpoints { + if debug_location == location { + result.push(*id); + } + } + for breakpoints in self.source_breakpoints.values() { + for (location, id) in breakpoints { + if debug_location == location { + result.push(*id); + } + } + } + result + } + + fn handle_execution_result(&mut self, result: DebugCommandResult) -> Result<(), ServerError> { + match result { + DebugCommandResult::Done => { + self.running = false; + } + DebugCommandResult::Ok => { + self.server.send_event(Event::Stopped(StoppedEventBody { + reason: StoppedEventReason::Pause, + description: None, + thread_id: Some(0), + preserve_focus_hint: Some(false), + text: None, + all_threads_stopped: Some(false), + hit_breakpoint_ids: None, + }))?; + } + DebugCommandResult::BreakpointReached(location) => { + let breakpoint_ids = self.find_breakpoints_at_location(&location); + self.server.send_event(Event::Stopped(StoppedEventBody { + reason: StoppedEventReason::Breakpoint, + description: Some(String::from("Paused at breakpoint")), + thread_id: Some(0), + preserve_focus_hint: Some(false), + text: None, + all_threads_stopped: Some(false), + hit_breakpoint_ids: Some(breakpoint_ids), + }))?; + } + DebugCommandResult::Error(err) => { + self.server.send_event(Event::Stopped(StoppedEventBody { + reason: StoppedEventReason::Exception, + description: Some(format!("{err:?}")), + thread_id: Some(0), + preserve_focus_hint: Some(false), + text: None, + all_threads_stopped: Some(false), + hit_breakpoint_ids: None, + }))?; + } + } + Ok(()) + } + + fn get_next_breakpoint_id(&mut self) -> BreakpointId { + let id = self.next_breakpoint_id; + self.next_breakpoint_id += 1; + id + } + + fn reinstall_breakpoints(&mut self) { + self.context.clear_breakpoints(); + for (location, _) in &self.instruction_breakpoints { + self.context.add_breakpoint(*location); + } + for breakpoints in self.source_breakpoints.values() { + for (location, _) in breakpoints { + self.context.add_breakpoint(*location); + } + } + } + + fn handle_set_instruction_breakpoints(&mut self, req: Request) -> Result<(), ServerError> { + let Command::SetInstructionBreakpoints(ref args) = req.command else { + unreachable!("handle_set_instruction_breakpoints called on a different request"); + }; + + // compute breakpoints to set and return + let mut breakpoints_to_set: Vec<(DebugLocation, i64)> = vec![]; + let breakpoints: Vec = args + .breakpoints + .iter() + .map(|breakpoint| { + 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("Invalid instruction reference/offset")), + ..Breakpoint::default() + }; + }; + let Some(location) = self + .context + .address_to_debug_location(address) + .filter(|location| self.context.is_valid_debug_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, + offset: Some(0), + instruction_reference: Some(address.to_string()), + ..Breakpoint::default() + } + }) + .collect(); + + // actually set the computed breakpoints + self.instruction_breakpoints = breakpoints_to_set; + self.reinstall_breakpoints(); + + // response to request + self.server.respond(req.success(ResponseBody::SetInstructionBreakpoints( + SetInstructionBreakpointsResponse { breakpoints }, + )))?; + Ok(()) + } + + fn find_file_id(&self, source_path: &str) -> Option { + let file_map = &self.debug_artifact.file_map; + let found = file_map.iter().find(|(_, debug_file)| match debug_file.path.to_str() { + Some(debug_file_path) => debug_file_path == source_path, + None => false, + }); + found.map(|iter| *iter.0) + } + + fn map_source_breakpoints(&mut self, args: &SetBreakpointsArguments) -> Vec { + let Some(ref source) = &args.source.path else { + return vec![]; + }; + let Some(file_id) = self.find_file_id(source) else { + eprintln!("WARN: file ID for source {source} not found"); + return vec![]; + }; + let Some(ref breakpoints) = &args.breakpoints else { + return vec![]; + }; + let mut breakpoints_to_set: Vec<(DebugLocation, i64)> = vec![]; + let breakpoints = breakpoints + .iter() + .map(|breakpoint| { + let line = breakpoint.line; + let Some(location) = self.context.find_opcode_for_source_location(&file_id, line) + else { + return Breakpoint { + verified: false, + message: Some(String::from( + "Source location cannot be matched to opcode location", + )), + ..Breakpoint::default() + }; + }; + // TODO: line will not necessarily be the one requested; we + // should do the reverse mapping and retrieve the actual source + // code line number + if !self.context.is_valid_debug_location(&location) { + return Breakpoint { + verified: false, + message: Some(String::from("Invalid opcode location")), + ..Breakpoint::default() + }; + } + let breakpoint_address = self.context.debug_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()), + line: Some(line), + instruction_reference: Some(instruction_reference), + offset: Some(0), + ..Breakpoint::default() + } + }) + .collect(); + + self.source_breakpoints.insert(file_id, breakpoints_to_set); + + breakpoints + } + + fn handle_set_source_breakpoints(&mut self, req: Request) -> Result<(), ServerError> { + let Command::SetBreakpoints(ref args) = req.command else { + unreachable!("handle_set_source_breakpoints called on a different request"); + }; + let breakpoints = self.map_source_breakpoints(args); + self.reinstall_breakpoints(); + self.server.respond( + req.success(ResponseBody::SetBreakpoints(SetBreakpointsResponse { breakpoints })), + )?; + Ok(()) + } + + fn handle_scopes(&mut self, req: Request) -> Result<(), ServerError> { + self.server.respond(req.success(ResponseBody::Scopes(ScopesResponse { + scopes: vec![ + Scope { + name: String::from("Locals"), + variables_reference: ScopeReferences::Locals as i64, + ..Scope::default() + }, + Scope { + name: String::from("Witness Map"), + variables_reference: ScopeReferences::WitnessMap as i64, + ..Scope::default() + }, + ], + })))?; + Ok(()) + } + + fn build_local_variables(&self) -> Vec { + 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::>(); + + variables.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()); + variables + } + + fn build_witness_map(&self) -> Vec { + self.context + .get_witness_map() + .clone() + .into_iter() + .map(|(witness, value)| Variable { + name: format!("_{}", witness.witness_index()), + value: format!("{value:?}"), + ..Variable::default() + }) + .collect() + } + + fn handle_variables(&mut self, req: Request) -> Result<(), ServerError> { + let Command::Variables(ref args) = req.command else { + unreachable!("handle_variables called on a different request"); + }; + let scope: ScopeReferences = args.variables_reference.into(); + let variables: Vec<_> = match scope { + ScopeReferences::Locals => self.build_local_variables(), + ScopeReferences::WitnessMap => self.build_witness_map(), + _ => { + eprintln!( + "handle_variables with an unknown variables_reference {}", + args.variables_reference + ); + vec![] + } + }; + self.server + .respond(req.success(ResponseBody::Variables(VariablesResponse { variables })))?; + Ok(()) + } +} + +pub fn run_session>( + server: Server, + solver: &B, + program: CompiledProgram, + initial_witness: WitnessMap, +) -> Result<(), ServerError> { + let debug_artifact = DebugArtifact { debug_symbols: program.debug, file_map: program.file_map }; + let mut session = DapSession::new( + server, + solver, + &program.program.functions, + &debug_artifact, + initial_witness, + &program.program.unconstrained_functions, + ); + + session.run_loop() +} diff --git a/tooling/debugger/src/errors.rs b/tooling/debugger/src/errors.rs new file mode 100644 index 00000000000..4578987d715 --- /dev/null +++ b/tooling/debugger/src/errors.rs @@ -0,0 +1,19 @@ +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum DapError { + #[error("{0}")] + PreFlightGenericError(String), + + #[error(transparent)] + LoadError(#[from] LoadError), + + #[error(transparent)] + ServerError(#[from] dap::errors::ServerError), +} + +#[derive(Debug, Error)] +pub enum LoadError { + #[error("{0}")] + Generic(String), +} diff --git a/tooling/debugger/src/foreign_calls.rs b/tooling/debugger/src/foreign_calls.rs new file mode 100644 index 00000000000..b92e22844ea --- /dev/null +++ b/tooling/debugger/src/foreign_calls.rs @@ -0,0 +1,195 @@ +use acvm::{ + acir::brillig::{ForeignCallParam, ForeignCallResult}, + pwg::ForeignCallWaitInfo, + AcirField, FieldElement, +}; +use nargo::{ + foreign_calls::{ + layers::Layer, DefaultForeignCallBuilder, ForeignCallError, ForeignCallExecutor, + }, + PrintOutput, +}; +use noirc_artifacts::debug::{DebugArtifact, DebugVars, StackFrame}; +use noirc_errors::debug_info::{DebugFnId, DebugVarId}; + +pub(crate) enum DebugForeignCall { + VarAssign, + VarDrop, + MemberAssign(u32), + DerefAssign, + FnEnter, + FnExit, +} + +impl DebugForeignCall { + pub(crate) fn lookup(op_name: &str) -> Option { + let member_pre = "__debug_member_assign_"; + if let Some(op_suffix) = op_name.strip_prefix(member_pre) { + let arity = + op_suffix.parse::().expect("failed to parse debug_member_assign arity"); + return Some(DebugForeignCall::MemberAssign(arity)); + } + match op_name { + "__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>; + fn current_stack_frame(&self) -> Option>; +} + +#[derive(Default)] +pub struct DefaultDebugForeignCallExecutor { + pub debug_vars: DebugVars, +} + +impl DefaultDebugForeignCallExecutor { + fn make( + output: PrintOutput<'_>, + ex: DefaultDebugForeignCallExecutor, + ) -> impl DebugForeignCallExecutor + '_ { + DefaultForeignCallBuilder::default().with_output(output).build().add_layer(ex) + } + + #[allow(clippy::new_ret_no_self, dead_code)] + pub fn new(output: PrintOutput<'_>) -> impl DebugForeignCallExecutor + '_ { + Self::make(output, Self::default()) + } + + pub fn from_artifact<'a>( + output: PrintOutput<'a>, + artifact: &DebugArtifact, + ) -> impl DebugForeignCallExecutor + 'a { + let mut ex = Self::default(); + ex.load_artifact(artifact); + Self::make(output, ex) + } + + pub fn load_artifact(&mut self, artifact: &DebugArtifact) { + // 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> { + self.debug_vars.get_variables() + } + + fn current_stack_frame(&self) -> Option> { + self.debug_vars.current_stack_frame() + } +} + +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, 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.fields()).collect(); + self.debug_vars.assign_var(var_id, &values); + } + Ok(ForeignCallResult::default()) + } + Some(DebugForeignCall::VarDrop) => { + 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); + self.debug_vars.drop_var(var_id); + } + Ok(ForeignCallResult::default()) + } + Some(DebugForeignCall::MemberAssign(arity)) => { + if let Some(ForeignCallParam::Single(var_id_value)) = foreign_call.inputs.first() { + let arity = arity as usize; + let var_id = debug_var_id(var_id_value); + let n = foreign_call.inputs.len(); + let indexes: Vec = foreign_call.inputs[(n - arity)..n] + .iter() + .map(|fcp_v| { + if let ForeignCallParam::Single(v) = fcp_v { + v.to_u128() as u32 + } else { + panic!("expected ForeignCallParam::Single(v)"); + } + }) + .collect(); + let values: Vec = (0..n - 1 - arity) + .flat_map(|i| { + foreign_call + .inputs + .get(1 + i) + .map(|fci| fci.fields()) + .unwrap_or_default() + }) + .collect(); + self.debug_vars.assign_field(var_id, indexes, &values); + } + 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.fields()); + } + 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 => Err(ForeignCallError::NoHandler(foreign_call_name.to_string())), + } + } +} + +impl DebugForeignCallExecutor for Layer +where + H: DebugForeignCallExecutor, + I: ForeignCallExecutor, +{ + fn get_variables(&self) -> Vec> { + self.handler().get_variables() + } + + fn current_stack_frame(&self) -> Option> { + self.handler().current_stack_frame() + } +} diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs new file mode 100644 index 00000000000..37ac088ca35 --- /dev/null +++ b/tooling/debugger/src/lib.rs @@ -0,0 +1,33 @@ +mod context; +mod dap; +pub mod errors; +mod foreign_calls; +mod repl; +mod source_code_printer; + +use std::io::{Read, Write}; + +use ::dap::errors::ServerError; +use ::dap::server::Server; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; +use acvm::{BlackBoxFunctionSolver, FieldElement}; + +use nargo::NargoError; +use noirc_driver::CompiledProgram; + +pub fn run_repl_session>( + solver: &B, + program: CompiledProgram, + initial_witness: WitnessMap, +) -> Result>, NargoError> { + repl::run(solver, program, initial_witness) +} + +pub fn run_dap_loop>( + server: Server, + solver: &B, + program: CompiledProgram, + 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 new file mode 100644 index 00000000000..eda3cbfd895 --- /dev/null +++ b/tooling/debugger/src/repl.rs @@ -0,0 +1,632 @@ +use crate::context::{DebugCommandResult, DebugContext, DebugLocation}; + +use acvm::acir::brillig::BitSize; +use acvm::acir::circuit::brillig::{BrilligBytecode, BrilligFunctionId}; +use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; +use acvm::acir::native_types::{Witness, WitnessMap, WitnessStack}; +use acvm::brillig_vm::brillig::Opcode as BrilligOpcode; +use acvm::brillig_vm::MemoryValue; +use acvm::AcirField; +use acvm::{BlackBoxFunctionSolver, FieldElement}; +use nargo::{NargoError, PrintOutput}; +use noirc_driver::CompiledProgram; + +use crate::foreign_calls::DefaultDebugForeignCallExecutor; +use noirc_artifacts::debug::DebugArtifact; + +use easy_repl::{command, CommandStatus, Repl}; +use noirc_printable_type::PrintableValueDisplay; +use std::cell::RefCell; + +use crate::source_code_printer::print_source_code_location; + +pub struct ReplDebugger<'a, B: BlackBoxFunctionSolver> { + context: DebugContext<'a, B>, + blackbox_solver: &'a B, + debug_artifact: &'a DebugArtifact, + initial_witness: WitnessMap, + last_result: DebugCommandResult, + + // ACIR functions to debug + circuits: &'a [Circuit], + + // Brillig functions referenced from the ACIR circuits above + unconstrained_functions: &'a [BrilligBytecode], +} + +impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { + pub fn new( + blackbox_solver: &'a B, + circuits: &'a [Circuit], + debug_artifact: &'a DebugArtifact, + initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], + ) -> Self { + let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact( + PrintOutput::Stdout, + debug_artifact, + )); + let context = DebugContext::new( + blackbox_solver, + circuits, + debug_artifact, + initial_witness.clone(), + foreign_call_executor, + unconstrained_functions, + ); + let last_result = if context.get_current_debug_location().is_none() { + // handle circuit with no opcodes + DebugCommandResult::Done + } else { + DebugCommandResult::Ok + }; + Self { + context, + blackbox_solver, + circuits, + debug_artifact, + initial_witness, + last_result, + unconstrained_functions, + } + } + + pub fn show_current_vm_status(&self) { + let location = self.context.get_current_debug_location(); + + match location { + None => println!("Finished execution"), + Some(location) => { + let circuit_id = location.circuit_id; + let opcodes = self.context.get_opcodes_of_circuit(circuit_id); + match &location.opcode_location { + OpcodeLocation::Acir(ip) => { + println!("At opcode {} :: {}", location, opcodes[*ip]); + } + OpcodeLocation::Brillig { acir_index, brillig_index } => { + 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 {} :: {:?}", + location, brillig_bytecode[*brillig_index] + ); + } + } + let locations = self.context.get_source_location_for_debug_location(&location); + print_source_code_location(self.debug_artifact, &locations); + } + } + } + + fn show_stack_frame(&self, index: usize, debug_location: &DebugLocation) { + let opcodes = self.context.get_opcodes(); + match &debug_location.opcode_location { + OpcodeLocation::Acir(instruction_pointer) => { + println!( + "Frame #{index}, opcode {} :: {}", + debug_location, opcodes[*instruction_pointer] + ) + } + OpcodeLocation::Brillig { acir_index, brillig_index } => { + 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 {} :: {:?}", + debug_location, brillig_bytecode[*brillig_index] + ); + } + } + let locations = self.context.get_source_location_for_debug_location(debug_location); + print_source_code_location(self.debug_artifact, &locations); + } + + pub fn show_current_call_stack(&self) { + let call_stack = self.context.get_call_stack(); + if call_stack.is_empty() { + println!("Finished execution. Call stack empty."); + return; + } + + for (i, frame_location) in call_stack.iter().enumerate() { + self.show_stack_frame(i, frame_location); + } + } + + fn display_opcodes(&self) { + for i in 0..self.circuits.len() { + self.display_opcodes_of_circuit(i as u32); + } + } + + fn display_opcodes_of_circuit(&self, circuit_id: u32) { + let current_opcode_location = + self.context.get_current_debug_location().and_then(|debug_location| { + if debug_location.circuit_id == circuit_id { + Some(debug_location.opcode_location) + } else { + None + } + }); + let opcodes = self.context.get_opcodes_of_circuit(circuit_id); + let current_acir_index = match current_opcode_location { + Some(OpcodeLocation::Acir(ip)) => Some(ip), + Some(OpcodeLocation::Brillig { acir_index, .. }) => Some(acir_index), + None => None, + }; + let current_brillig_index = match current_opcode_location { + Some(OpcodeLocation::Brillig { brillig_index, .. }) => brillig_index, + _ => 0, + }; + let outer_marker = |acir_index| { + if current_acir_index == Some(acir_index) { + "->" + } else if self.context.is_breakpoint_set(&DebugLocation { + circuit_id, + opcode_location: OpcodeLocation::Acir(acir_index), + brillig_function_id: None, + }) { + " *" + } else { + "" + } + }; + let brillig_marker = |acir_index, brillig_index, brillig_function_id| { + if current_acir_index == Some(acir_index) && brillig_index == current_brillig_index { + "->" + } else if self.context.is_breakpoint_set(&DebugLocation { + circuit_id, + opcode_location: OpcodeLocation::Brillig { acir_index, brillig_index }, + brillig_function_id: Some(brillig_function_id), + }) { + " *" + } else { + "" + } + }; + let print_brillig_bytecode = + |acir_index, + bytecode: &[BrilligOpcode], + brillig_function_id: BrilligFunctionId| { + for (brillig_index, brillig_opcode) in bytecode.iter().enumerate() { + println!( + "{:>2}:{:>3}.{:<2} |{:2} {:?}", + circuit_id, + acir_index, + brillig_index, + brillig_marker(acir_index, brillig_index, brillig_function_id), + brillig_opcode + ); + } + }; + for (acir_index, opcode) in opcodes.iter().enumerate() { + let marker = outer_marker(acir_index); + match &opcode { + Opcode::BrilligCall { id, inputs, outputs, .. } => { + println!( + "{:>2}:{:>3} {:2} BRILLIG CALL id={} inputs={:?}", + circuit_id, acir_index, marker, id, inputs + ); + println!(" | outputs={:?}", outputs); + let bytecode = &self.unconstrained_functions[id.as_usize()].bytecode; + print_brillig_bytecode(acir_index, bytecode, *id); + } + _ => println!("{:>2}:{:>3} {:2} {:?}", circuit_id, acir_index, marker, opcode), + } + } + } + + fn add_breakpoint_at(&mut self, location: DebugLocation) { + if !self.context.is_valid_debug_location(&location) { + println!("Invalid location {location}"); + } else if self.context.add_breakpoint(location) { + println!("Added breakpoint at {location}"); + } else { + println!("Breakpoint at {location} already set"); + } + } + + fn delete_breakpoint_at(&mut self, location: DebugLocation) { + if self.context.delete_breakpoint(&location) { + println!("Breakpoint at {location} deleted"); + } else { + println!("Breakpoint at {location} not set"); + } + } + + fn validate_in_progress(&self) -> bool { + match self.last_result { + DebugCommandResult::Ok | DebugCommandResult::BreakpointReached(..) => true, + DebugCommandResult::Done => { + println!("Execution finished"); + false + } + DebugCommandResult::Error(ref error) => { + println!("ERROR: {}", error); + self.show_current_vm_status(); + false + } + } + } + + fn handle_debug_command_result(&mut self, result: DebugCommandResult) { + match &result { + DebugCommandResult::BreakpointReached(location) => { + println!("Stopped at breakpoint in opcode {}", location); + } + DebugCommandResult::Error(error) => { + println!("ERROR: {}", error); + } + _ => (), + } + self.last_result = result; + self.show_current_vm_status(); + } + + fn step_acir_opcode(&mut self) { + if self.validate_in_progress() { + let result = self.context.step_acir_opcode(); + self.handle_debug_command_result(result); + } + } + + fn step_into_opcode(&mut self) { + if self.validate_in_progress() { + let result = self.context.step_into_opcode(); + self.handle_debug_command_result(result); + } + } + + fn next_into(&mut self) { + if self.validate_in_progress() { + let result = self.context.next_into(); + self.handle_debug_command_result(result); + } + } + + fn next_over(&mut self) { + if self.validate_in_progress() { + let result = self.context.next_over(); + self.handle_debug_command_result(result); + } + } + + fn next_out(&mut self) { + if self.validate_in_progress() { + let result = self.context.next_out(); + self.handle_debug_command_result(result); + } + } + + fn cont(&mut self) { + if self.validate_in_progress() { + println!("(Continuing execution...)"); + let result = self.context.cont(); + self.handle_debug_command_result(result); + } + } + + fn restart_session(&mut self) { + let breakpoints: Vec = self.context.iterate_breakpoints().copied().collect(); + let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact( + PrintOutput::Stdout, + self.debug_artifact, + )); + self.context = DebugContext::new( + self.blackbox_solver, + self.circuits, + self.debug_artifact, + self.initial_witness.clone(), + foreign_call_executor, + self.unconstrained_functions, + ); + for debug_location in breakpoints { + self.context.add_breakpoint(debug_location); + } + self.last_result = DebugCommandResult::Ok; + println!("Restarted debugging session."); + self.show_current_vm_status(); + } + + pub fn show_witness_map(&self) { + let witness_map = self.context.get_witness_map(); + // NOTE: we need to clone() here to get the iterator + for (witness, value) in witness_map.clone().into_iter() { + println!("_{} = {value}", witness.witness_index()); + } + } + + pub fn show_witness(&self, index: u32) { + if let Some(value) = self.context.get_witness_map().get_index(index) { + println!("_{} = {value}", index); + } + } + + pub fn update_witness(&mut self, index: u32, value: String) { + let Some(field_value) = FieldElement::try_from_str(&value) else { + println!("Invalid witness value: {value}"); + return; + }; + + let witness = Witness::from(index); + _ = self.context.overwrite_witness(witness, field_value); + println!("_{} = {value}", index); + } + + pub fn show_brillig_memory(&self) { + if !self.context.is_executing_brillig() { + println!("Not executing a Brillig block"); + return; + } + + let Some(memory) = self.context.get_brillig_memory() else { + // this can happen when just entering the Brillig block since ACVM + // would have not initialized the Brillig VM yet; in fact, the + // Brillig code may be skipped altogether + println!("Brillig VM memory not available"); + return; + }; + + for (index, value) in memory.iter().enumerate() { + // Zero field is the default value, we omit it when printing memory + if let MemoryValue::Field(field) = value { + if field == &FieldElement::zero() { + continue; + } + } + println!("{index} = {}", value); + } + } + + 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; + }; + + let Ok(bit_size) = BitSize::try_from_u32::(bit_size) else { + println!("Invalid bit size: {bit_size}"); + return; + }; + + if !self.context.is_executing_brillig() { + println!("Not executing a Brillig block"); + return; + } + self.context.write_brillig_memory(index, field_value, bit_size); + } + + pub fn show_vars(&self) { + 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); + } + } + } + + fn is_solved(&self) -> bool { + self.context.is_solved() + } + + fn finalize(self) -> WitnessStack { + self.context.finalize() + } +} + +pub fn run>( + blackbox_solver: &B, + program: CompiledProgram, + initial_witness: WitnessMap, +) -> Result>, NargoError> { + let circuits = &program.program.functions; + let debug_artifact = + &DebugArtifact { debug_symbols: program.debug, file_map: program.file_map }; + let unconstrained_functions = &program.program.unconstrained_functions; + let context = RefCell::new(ReplDebugger::new( + blackbox_solver, + circuits, + debug_artifact, + initial_witness, + unconstrained_functions, + )); + let ref_context = &context; + + ref_context.borrow().show_current_vm_status(); + + let mut repl = Repl::builder() + .add( + "step", + command! { + "step to the next ACIR opcode", + () => || { + ref_context.borrow_mut().step_acir_opcode(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "into", + command! { + "step into to the next opcode", + () => || { + ref_context.borrow_mut().step_into_opcode(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "next", + command! { + "step until a new source location is reached", + () => || { + ref_context.borrow_mut().next_into(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "over", + command! { + "step until a new source location is reached without diving into function calls", + () => || { + ref_context.borrow_mut().next_over(); + Ok(CommandStatus::Done) + } + } + ) + .add( + "out", + command! { + "step until a new source location is reached and the current stack frame is finished", + () => || { + ref_context.borrow_mut().next_out(); + Ok(CommandStatus::Done) + } + } + ) + .add( + "continue", + command! { + "continue execution until the end of the program", + () => || { + ref_context.borrow_mut().cont(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "restart", + command! { + "restart the debugging session", + () => || { + ref_context.borrow_mut().restart_session(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "opcodes", + command! { + "display ACIR opcodes", + () => || { + ref_context.borrow().display_opcodes(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "break", + command! { + "add a breakpoint at an opcode location", + (LOCATION:DebugLocation) => |location| { + ref_context.borrow_mut().add_breakpoint_at(location); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "delete", + command! { + "delete breakpoint at an opcode location", + (LOCATION:DebugLocation) => |location| { + ref_context.borrow_mut().delete_breakpoint_at(location); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "witness", + command! { + "show witness map", + () => || { + ref_context.borrow().show_witness_map(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "witness", + command! { + "display a single witness from the witness map", + (index: u32) => |index| { + ref_context.borrow().show_witness(index); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "witness", + command! { + "update a witness with the given value", + (index: u32, value: String) => |index, value| { + ref_context.borrow_mut().update_witness(index, value); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "memory", + command! { + "show Brillig memory (valid when executing a Brillig block)", + () => || { + ref_context.borrow().show_brillig_memory(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "memset", + command! { + "update a Brillig memory cell with the given value", + (index: usize, value: String, bit_size: u32) => |index, value, bit_size| { + ref_context.borrow_mut().write_brillig_memory(index, value, bit_size); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "stacktrace", + command! { + "display the current stack trace", + () => || { + ref_context.borrow().show_current_call_stack(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "vars", + command! { + "show variables for each function scope available at this point in execution", + () => || { + ref_context.borrow_mut().show_vars(); + Ok(CommandStatus::Done) + } + }, + ) + .build() + .expect("Failed to initialize debugger repl"); + + repl.run().expect("Debugger error"); + + // REPL execution has finished. + // Drop it so that we can move fields out from `context` again. + drop(repl); + + if context.borrow().is_solved() { + let solved_witness_stack = context.into_inner().finalize(); + Ok(Some(solved_witness_stack)) + } else { + Ok(None) + } +} diff --git a/tooling/debugger/src/source_code_printer.rs b/tooling/debugger/src/source_code_printer.rs new file mode 100644 index 00000000000..b3682c9016f --- /dev/null +++ b/tooling/debugger/src/source_code_printer.rs @@ -0,0 +1,317 @@ +use codespan_reporting::files::Files; +use noirc_artifacts::debug::DebugArtifact; +use noirc_errors::Location; +use owo_colors::OwoColorize; +use std::ops::Range; + +#[derive(Debug, PartialEq)] +enum PrintedLine<'a> { + Skip, + Ellipsis { + line_number: usize, + }, + Content { + line_number: usize, + cursor: &'a str, + content: &'a str, + highlight: Option>, + }, +} + +#[derive(Clone, Debug)] +struct LocationPrintContext { + file_lines: Range, + printed_lines: Range, + location_lines: Range, + location_offset_in_first_line: Range, + location_offset_in_last_line: Range, +} + +// 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(super) fn print_source_code_location(debug_artifact: &DebugArtifact, locations: &[Location]) { + let locations = locations.iter(); + + for loc in locations { + print_location_path(debug_artifact, *loc); + + let lines = render_location(debug_artifact, loc); + + for line in lines { + match line { + PrintedLine::Skip => {} + PrintedLine::Ellipsis { line_number } => print_ellipsis(line_number), + PrintedLine::Content { line_number, cursor, content, highlight } => { + print_content(line_number, cursor, content, highlight) + } + } + } + } +} + +fn print_location_path(debug_artifact: &DebugArtifact, loc: Location) { + let line_number = debug_artifact.location_line_number(loc).unwrap(); + let column_number = debug_artifact.location_column_number(loc).unwrap(); + + println!("At {}:{line_number}:{column_number}", debug_artifact.name(loc.file).unwrap()); +} + +fn print_ellipsis(line_number: usize) { + println!("{:>3} {:2} {}", line_number.dimmed(), "", "...".dimmed()); +} + +fn print_content(line_number: usize, cursor: &str, content: &str, highlight: Option>) { + match highlight { + Some(highlight) => { + println!( + "{:>3} {:2} {}{}{}", + line_number, + cursor, + content[0..highlight.start].to_string().dimmed(), + &content[highlight.start..highlight.end], + content[highlight.end..].to_string().dimmed(), + ); + } + None => { + println!( + "{:>3} {:2} {}", + line_number.dimmed(), + cursor.dimmed(), + content.to_string().dimmed(), + ); + } + } +} + +fn render_line( + current: usize, + content: &str, + loc_context: LocationPrintContext, +) -> PrintedLine<'_> { + let file_lines = loc_context.file_lines; + let printed_lines = loc_context.printed_lines; + let location_lines = loc_context.location_lines; + let line_number = current + 1; + + if current < printed_lines.start { + // Ignore lines before the context window we choose to show + PrintedLine::Skip + } else if 0 < current && current == printed_lines.start && current < location_lines.start { + // Denote that there's more lines before but we're not showing them + PrintedLine::Ellipsis { line_number } + } else if current < location_lines.start { + // Print lines before the location start without highlighting + PrintedLine::Content { line_number, cursor: "", content, highlight: None } + } else if current == location_lines.start { + // Highlight current location from where it starts to the end of the current line + PrintedLine::Content { + line_number, + cursor: "->", + content, + highlight: Some(loc_context.location_offset_in_first_line), + } + } else if current < location_lines.end { + // Highlight current line if it's contained by the current location + PrintedLine::Content { + line_number, + cursor: "", + content, + highlight: Some(Range { start: 0, end: content.len() }), + } + } else if current == location_lines.end { + // Highlight current location from the beginning of the line until the location's own end + PrintedLine::Content { + line_number, + cursor: "", + content, + highlight: Some(loc_context.location_offset_in_last_line), + } + } else if current < printed_lines.end || printed_lines.end == file_lines.end { + // Print lines after the location end without highlighting + PrintedLine::Content { line_number, cursor: "", content, highlight: None } + } else if current == printed_lines.end && printed_lines.end < file_lines.end { + // Denote that there's more lines after but we're not showing them + PrintedLine::Ellipsis { line_number } + } else { + PrintedLine::Skip + } +} + +// Given a Location in a DebugArtifact, returns a line iterator that specifies how to +// print the location's file. +// +// Consider for example the file (line numbers added to facilitate this doc): +// ``` +// 1 use std::hash::poseidon; +// 2 +// 3 fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { +// 4 let hash1 = poseidon::bn254::hash_2(x1); +// 5 assert(hash1 == y1); +// 6 +// 7 let hash2 = poseidon::bn254::hash_4(x2); +// 8 assert(hash2 == y2); +// 9 } +// 10 +// ``` +// +// If the location to render is `poseidon::bn254::hash_2(x1)`, we'll render the file as: +// ``` +// 1 use std::hash::poseidon; +// 2 +// 3 fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { +// 4 let hash1 = poseidon::bn254::hash_2(x1); +// 5 -> assert(hash1 == y1); +// 6 +// 7 let hash2 = poseidon::bn254::hash_4(x2); +// 8 assert(hash2 == y2); +// 9 } +// 10 ... +// ``` +// +// This is the result of: +// 1. Limiting the amount of printed lines to 5 before and 5 after the location. +// 2. Using ellipsis (...) to denote when some file lines have been left out of the render. +// 3. Using an arrow cursor (->) to denote where the rendered location starts. +// 4. Highlighting the location (here expressed as a block for the sake of the explanation). +// +// Note that locations may span multiple lines, so this function deals with that too. +fn render_location<'a>( + debug_artifact: &'a DebugArtifact, + loc: &'a Location, +) -> impl Iterator> { + let loc = *loc; + + let file_lines = Range { start: 0, end: debug_artifact.last_line_index(loc).unwrap() }; + + // Sub-range of file lines that this location spans + let location_lines = Range { + start: debug_artifact.location_line_index(loc).unwrap(), + end: debug_artifact.location_end_line_index(loc).unwrap(), + }; + + // How many lines before or after the location's lines we print + let context_lines = 5; + + // Sub-range of lines that we'll print, which includes location + context lines + let first_line_to_print = + if location_lines.start < context_lines { 0 } else { location_lines.start - context_lines }; + let last_line_to_print = std::cmp::min(location_lines.end + context_lines, file_lines.end); + let printed_lines = Range { start: first_line_to_print, end: last_line_to_print }; + + // Range of the location relative to its starting and ending lines + let location_offset_in_first_line = debug_artifact.location_in_line(loc).unwrap(); + let location_offset_in_last_line = debug_artifact.location_in_end_line(loc).unwrap(); + + let context = LocationPrintContext { + file_lines, + printed_lines, + location_lines, + location_offset_in_first_line, + location_offset_in_last_line, + }; + + let source = debug_artifact.location_source_code(loc).unwrap(); + source + .lines() + .enumerate() + .map(move |(index, content)| render_line(index, content, context.clone())) +} + +#[cfg(test)] +mod tests { + use crate::source_code_printer::render_location; + use crate::source_code_printer::PrintedLine::Content; + use acvm::acir::circuit::OpcodeLocation; + use fm::FileManager; + use noirc_artifacts::debug::DebugArtifact; + use noirc_errors::{debug_info::DebugInfo, Location, Span}; + use std::collections::BTreeMap; + use std::ops::Range; + use std::path::Path; + use std::path::PathBuf; + use tempfile::{tempdir, TempDir}; + + // Returns the absolute path to the file + fn create_dummy_file(dir: &TempDir, file_name: &Path) -> PathBuf { + let file_path = dir.path().join(file_name); + let _file = std::fs::File::create(&file_path).unwrap(); + file_path + } + + #[test] + fn render_multiple_line_location() { + let source_code = r##"pub fn main(mut state: [Field; 2]) -> [Field; 2] { + state = permute( + consts::x5_2_config(), + state); + + state +}"##; + + let dir = tempdir().unwrap(); + let file_name = Path::new("main.nr"); + create_dummy_file(&dir, file_name); + + let mut fm = FileManager::new(dir.path()); + let file_id = fm.add_file_with_source(file_name, source_code.to_string()).unwrap(); + + // Location of + // ``` + // permute( + // consts::x5_2_config(), + // state) + // ``` + let loc = Location::new(Span::inclusive(63, 116), file_id); + + // We don't care about opcodes in this context, + // we just use a dummy to construct debug_symbols + 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(), + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + )]; + let debug_artifact = DebugArtifact::new(debug_symbols, &fm); + + let location_rendered: Vec<_> = render_location(&debug_artifact, &loc).collect(); + + assert_eq!( + location_rendered, + vec![ + Content { + line_number: 1, + cursor: "", + content: "pub fn main(mut state: [Field; 2]) -> [Field; 2] {", + highlight: None, + }, + Content { + line_number: 2, + cursor: "->", + content: " state = permute(", + highlight: Some(Range { start: 12, end: 20 }), + }, + Content { + line_number: 3, + cursor: "", + content: " consts::x5_2_config(),", + highlight: Some(Range { start: 0, end: 30 }), + }, + Content { + line_number: 4, + cursor: "", + content: " state);", + highlight: Some(Range { start: 0, end: 14 }), + }, + Content { line_number: 5, cursor: "", content: "", highlight: None }, + Content { line_number: 6, cursor: "", content: " state", highlight: None }, + Content { line_number: 7, cursor: "", content: "}", highlight: None }, + ] + ); + } +} diff --git a/tooling/debugger/tests/debug.rs b/tooling/debugger/tests/debug.rs new file mode 100644 index 00000000000..eb43cf9cc6d --- /dev/null +++ b/tooling/debugger/tests/debug.rs @@ -0,0 +1,52 @@ +#[cfg(test)] +mod tests { + // Some of these imports are consumed by the injected tests + use assert_cmd::cargo::cargo_bin; + + use rexpect::spawn_bash; + + // include tests generated by `build.rs` + include!(concat!(env!("OUT_DIR"), "/debug.rs")); + + pub fn debugger_execution_success(test_program_dir: &str) { + let nargo_bin = + cargo_bin("nargo").into_os_string().into_string().expect("Cannot parse nargo path"); + + let timeout_seconds = 30; + 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 + .execute( + &format!( + "{nargo_bin} debug --program-dir {test_program_dir} --force-brillig --expression-width 3" + ), + ".*\\Starting debugger.*", + ) + .expect("Could not start debugger"); + + // While running the debugger, issue a "continue" cmd, + // which should run to the program to end given + // we haven't set any breakpoints. + // ">" is the debugger's prompt, so finding one + // after running "continue" indicates that the + // debugger has not panicked until the end of the program. + dbg_session + .send_line("c") + .expect("Debugger panicked while attempting to step through program."); + dbg_session + .exp_string(">") + .expect("Failed while waiting for debugger to step through program."); + + // Run the "quit" command, then check that the debugger confirms + // having successfully solved the circuit witness. + dbg_session.send_line("quit").expect("Failed to quit debugger"); + 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/fuzzer/Cargo.toml b/tooling/fuzzer/Cargo.toml new file mode 100644 index 00000000000..31701991844 --- /dev/null +++ b/tooling/fuzzer/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "noir_fuzzer" +description = "A fuzzer for Noir programs" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[lints] +workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +acvm.workspace = true +noirc_artifacts.workspace = true +noirc_abi.workspace = true +proptest.workspace = true +rand.workspace = true diff --git a/tooling/fuzzer/src/dictionary/mod.rs b/tooling/fuzzer/src/dictionary/mod.rs new file mode 100644 index 00000000000..7fe1c4cd602 --- /dev/null +++ b/tooling/fuzzer/src/dictionary/mod.rs @@ -0,0 +1,138 @@ +//! This module defines how to build a dictionary of values which are likely to be correspond +//! to significant inputs during fuzzing by inspecting the [Program] being fuzzed. +//! +//! This dictionary can be fed into the fuzzer's [strategy][proptest::strategy::Strategy] in order to bias it towards +//! generating these values to ensure they get proper coverage. +use std::collections::HashSet; + +use acvm::{ + acir::{ + circuit::{ + brillig::{BrilligBytecode, BrilligInputs}, + opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum}, + Circuit, Opcode, Program, + }, + native_types::Expression, + }, + brillig_vm::brillig::Opcode as BrilligOpcode, + AcirField, +}; + +/// Constructs a [HashSet] of values pulled from a [Program] which are likely to be correspond +/// to significant inputs during fuzzing. +pub(super) fn build_dictionary_from_program(program: &Program) -> HashSet { + let constrained_dictionaries = program.functions.iter().map(build_dictionary_from_circuit); + let unconstrained_dictionaries = + program.unconstrained_functions.iter().map(build_dictionary_from_unconstrained_function); + let dictionaries = constrained_dictionaries.chain(unconstrained_dictionaries); + + let mut constants: HashSet = HashSet::new(); + for dictionary in dictionaries { + constants.extend(dictionary); + } + constants +} + +/// Collect `Field` values used in the opcodes of an ACIR circuit. +fn build_dictionary_from_circuit(circuit: &Circuit) -> HashSet { + let mut constants: HashSet = HashSet::new(); + + /// Pull out all the fields from an expression. + fn insert_expr(dictionary: &mut HashSet, expr: &Expression) { + let quad_coefficients = expr.mul_terms.iter().map(|(k, _, _)| *k); + let linear_coefficients = expr.linear_combinations.iter().map(|(k, _)| *k); + let coefficients = linear_coefficients.chain(quad_coefficients); + + dictionary.extend(coefficients.clone()); + dictionary.insert(expr.q_c); + + // We divide the constant term by any coefficients in the expression to aid solving constraints such as `2 * x - 4 == 0`. + let scaled_constants = coefficients.map(|coefficient| expr.q_c / coefficient); + dictionary.extend(scaled_constants); + } + + fn insert_array_len(dictionary: &mut HashSet, array: &[T]) { + let array_length = array.len() as u128; + dictionary.insert(F::from(array_length)); + dictionary.insert(F::from(array_length - 1)); + } + + for opcode in &circuit.opcodes { + match opcode { + Opcode::AssertZero(expr) + | Opcode::Call { predicate: Some(expr), .. } + | Opcode::MemoryOp { predicate: Some(expr), .. } => insert_expr(&mut constants, expr), + + Opcode::MemoryInit { init, .. } => insert_array_len(&mut constants, init), + + Opcode::BrilligCall { inputs, predicate, .. } => { + for input in inputs { + match input { + BrilligInputs::Single(expr) => insert_expr(&mut constants, expr), + BrilligInputs::Array(exprs) => { + exprs.iter().for_each(|expr| insert_expr(&mut constants, expr)); + insert_array_len(&mut constants, exprs); + } + BrilligInputs::MemoryArray(_) => (), + } + } + if let Some(predicate) = predicate { + insert_expr(&mut constants, predicate) + } + } + + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { input }) + if matches!(input.input(), ConstantOrWitnessEnum::Constant(..)) => + { + match input.input() { + ConstantOrWitnessEnum::Constant(c) => { + let field = 1u128.wrapping_shl(input.num_bits()); + constants.insert(F::from(field)); + constants.insert(F::from(field - 1)); + constants.insert(c); + } + _ => { + let field = 1u128.wrapping_shl(input.num_bits()); + constants.insert(F::from(field)); + constants.insert(F::from(field - 1)); + } + } + } + + _ => (), + } + } + + constants +} + +/// Collect `Field` values used in the opcodes of a Brillig function. +fn build_dictionary_from_unconstrained_function( + function: &BrilligBytecode, +) -> HashSet { + let mut constants: HashSet = HashSet::new(); + + for opcode in &function.bytecode { + match opcode { + BrilligOpcode::Cast { bit_size, .. } => { + let bit_size = bit_size.to_u32::(); + + let field = 1u128.wrapping_shl(bit_size); + constants.insert(F::from(field)); + constants.insert(F::from(field - 1)); + } + BrilligOpcode::Const { bit_size, value, .. } => { + let bit_size = bit_size.to_u32::(); + + constants.insert(*value); + + let field = 1u128.wrapping_shl(bit_size); + constants.insert(F::from(field)); + constants.insert(F::from(field - 1)); + } + _ => (), + } + } + + constants +} diff --git a/tooling/fuzzer/src/lib.rs b/tooling/fuzzer/src/lib.rs new file mode 100644 index 00000000000..324be323fc2 --- /dev/null +++ b/tooling/fuzzer/src/lib.rs @@ -0,0 +1,104 @@ +//! This module has been adapted from Foundry's fuzzing implementation for the EVM. +//! https://github.com/foundry-rs/foundry/blob/6a85dbaa62f1c305f31cab37781232913055ae28/crates/evm/evm/src/executors/fuzz/mod.rs#L40 +//! +//! Code is used under the MIT license. + +use acvm::{ + acir::{ + circuit::Program, + native_types::{WitnessMap, WitnessStack}, + }, + FieldElement, +}; +use dictionary::build_dictionary_from_program; +use noirc_abi::InputMap; +use proptest::test_runner::{TestCaseError, TestError, TestRunner}; + +mod dictionary; +mod strategies; +mod types; + +use types::{CaseOutcome, CounterExampleOutcome, FuzzOutcome, FuzzTestResult}; + +use noirc_artifacts::program::ProgramArtifact; + +/// An executor for Noir programs which provides fuzzing support using [`proptest`]. +/// +/// After instantiation, calling `fuzz` will proceed to hammer the program with +/// inputs, until it finds a counterexample. The provided [`TestRunner`] contains all the +/// configuration which can be overridden via [environment variables](proptest::test_runner::Config) +pub struct FuzzedExecutor { + /// The program to be fuzzed + program: ProgramArtifact, + + /// A function which executes the programs with a given set of inputs + executor: E, + + /// The fuzzer + runner: TestRunner, +} + +impl FuzzedExecutor +where + E: Fn( + &Program, + WitnessMap, + ) -> Result, String>, +{ + /// Instantiates a fuzzed executor given a [TestRunner]. + pub fn new(program: ProgramArtifact, executor: E, runner: TestRunner) -> Self { + Self { program, executor, runner } + } + + /// Fuzzes the provided program. + pub fn fuzz(&self) -> FuzzTestResult { + let dictionary = build_dictionary_from_program(&self.program.bytecode); + let strategy = strategies::arb_input_map(&self.program.abi, &dictionary); + + let run_result: Result<(), TestError> = + self.runner.clone().run(&strategy, |input_map| { + let fuzz_res = self.single_fuzz(input_map)?; + + match fuzz_res { + FuzzOutcome::Case(_) => Ok(()), + FuzzOutcome::CounterExample(CounterExampleOutcome { + exit_reason: status, + .. + }) => Err(TestCaseError::fail(status)), + } + }); + + match run_result { + Ok(()) => FuzzTestResult { success: true, reason: None, counterexample: None }, + + Err(TestError::Abort(reason)) => FuzzTestResult { + success: false, + reason: Some(reason.to_string()), + counterexample: None, + }, + Err(TestError::Fail(reason, counterexample)) => { + let reason = reason.to_string(); + let reason = if reason.is_empty() { None } else { Some(reason) }; + + FuzzTestResult { success: false, reason, counterexample: Some(counterexample) } + } + } + } + + /// Granular and single-step function that runs only one fuzz and returns either a `CaseOutcome` + /// or a `CounterExampleOutcome` + pub fn single_fuzz(&self, input_map: InputMap) -> Result { + let initial_witness = self.program.abi.encode(&input_map, None).unwrap(); + let result = (self.executor)(&self.program.bytecode, initial_witness); + + // TODO: Add handling for `vm.assume` equivalent + + match result { + Ok(_) => Ok(FuzzOutcome::Case(CaseOutcome { case: input_map })), + Err(err) => Ok(FuzzOutcome::CounterExample(CounterExampleOutcome { + exit_reason: err, + counterexample: input_map, + })), + } + } +} diff --git a/tooling/fuzzer/src/strategies/int.rs b/tooling/fuzzer/src/strategies/int.rs new file mode 100644 index 00000000000..22dded7c7b7 --- /dev/null +++ b/tooling/fuzzer/src/strategies/int.rs @@ -0,0 +1,87 @@ +use proptest::{ + strategy::{NewTree, Strategy}, + test_runner::TestRunner, +}; +use rand::Rng; + +type BinarySearch = proptest::num::i128::BinarySearch; + +/// Strategy for signed ints (up to i128). +/// The strategy combines 2 different strategies, each assigned a specific weight: +/// 1. Generate purely random value in a range. This will first choose bit size uniformly (up `bits` +/// param). Then generate a value for this bit size. +/// 2. Generate a random value around the edges (+/- 3 around min, 0 and max possible value) +#[derive(Debug)] +pub struct IntStrategy { + /// Bit size of int (e.g. 128) + bits: usize, + /// The weight for edge cases (+/- 3 around 0 and max possible value) + edge_weight: usize, + /// The weight for purely random values + random_weight: usize, +} + +impl IntStrategy { + /// Create a new strategy. + /// # Arguments + /// * `bits` - Size of int in bits + pub fn new(bits: usize) -> Self { + Self { bits, edge_weight: 10usize, random_weight: 50usize } + } + + /// Generate random values near MIN or the MAX value. + fn generate_edge_tree(&self, runner: &mut TestRunner) -> NewTree { + let rng = runner.rng(); + + let offset = rng.gen_range(0..4); + // Choose if we want values around min, -0, +0, or max + let kind = rng.gen_range(0..4); + let start = match kind { + 0 => self.type_min() + offset, + 1 => -offset - 1i128, + 2 => offset, + 3 => self.type_max() - offset, + _ => unreachable!(), + }; + Ok(BinarySearch::new(start)) + } + + fn generate_random_tree(&self, runner: &mut TestRunner) -> NewTree { + let rng = runner.rng(); + let start: i128 = rng.gen_range(self.type_min()..=self.type_max()); + Ok(BinarySearch::new(start)) + } + + /// Maximum allowed positive number. + fn type_max(&self) -> i128 { + if self.bits < 128 { + (1i128 << (self.bits - 1)) - 1 + } else { + i128::MAX + } + } + + /// Minimum allowed negative number. + fn type_min(&self) -> i128 { + if self.bits < 128 { + -(1i128 << (self.bits - 1)) + } else { + i128::MIN + } + } +} + +impl Strategy for IntStrategy { + type Tree = BinarySearch; + type Value = i128; + + fn new_tree(&self, runner: &mut TestRunner) -> NewTree { + let total_weight = self.random_weight + self.edge_weight; + let bias = runner.rng().gen_range(0..total_weight); + // randomly select one of 2 strategies + match bias { + x if x < self.edge_weight => self.generate_edge_tree(runner), + _ => self.generate_random_tree(runner), + } + } +} diff --git a/tooling/fuzzer/src/strategies/mod.rs b/tooling/fuzzer/src/strategies/mod.rs new file mode 100644 index 00000000000..99c7ca56f2e --- /dev/null +++ b/tooling/fuzzer/src/strategies/mod.rs @@ -0,0 +1,103 @@ +use int::IntStrategy; +use prop::collection::vec; +use proptest::prelude::*; + +use acvm::{AcirField, FieldElement}; + +use noirc_abi::{input_parser::InputValue, Abi, AbiType, InputMap, Sign}; +use std::collections::{BTreeMap, HashSet}; +use uint::UintStrategy; + +mod int; +mod uint; + +/// Create a strategy for generating random values for an [AbiType]. +/// +/// Uses the `dictionary` for unsigned integer types. +pub(super) fn arb_value_from_abi_type( + abi_type: &AbiType, + dictionary: &HashSet, +) -> SBoxedStrategy { + match abi_type { + AbiType::Field => vec(any::(), 32) + .prop_map(|bytes| InputValue::Field(FieldElement::from_be_bytes_reduce(&bytes))) + .sboxed(), + AbiType::Integer { width, sign } if sign == &Sign::Unsigned => { + // We've restricted the type system to only allow u64s as the maximum integer type. + let width = (*width).min(64); + UintStrategy::new(width as usize, dictionary) + .prop_map(|uint| InputValue::Field(uint.into())) + .sboxed() + } + AbiType::Integer { width, .. } => { + let width = (*width).min(64); + let shift = 2i128.pow(width); + IntStrategy::new(width as usize) + .prop_map(move |mut int| { + if int < 0 { + int += shift + } + InputValue::Field(int.into()) + }) + .sboxed() + } + AbiType::Boolean => { + any::().prop_map(|val| InputValue::Field(FieldElement::from(val))).sboxed() + } + AbiType::String { length } => { + // Strings only allow ASCII characters as each character must be able to be represented by a single byte. + let string_regex = format!("[[:ascii:]]{{{length}}}"); + proptest::string::string_regex(&string_regex) + .expect("parsing of regex should always succeed") + .prop_map(InputValue::String) + .sboxed() + } + AbiType::Array { length, typ } => { + let length = *length as usize; + let elements = vec(arb_value_from_abi_type(typ, dictionary), length..=length); + + elements.prop_map(InputValue::Vec).sboxed() + } + AbiType::Struct { fields, .. } => { + let fields: Vec> = fields + .iter() + .map(|(name, typ)| { + (Just(name.clone()), arb_value_from_abi_type(typ, dictionary)).sboxed() + }) + .collect(); + + fields + .prop_map(|fields| { + let fields: BTreeMap<_, _> = fields.into_iter().collect(); + InputValue::Struct(fields) + }) + .sboxed() + } + AbiType::Tuple { fields } => { + let fields: Vec<_> = + fields.iter().map(|typ| arb_value_from_abi_type(typ, dictionary)).collect(); + fields.prop_map(InputValue::Vec).sboxed() + } + } +} + +/// Given the [Abi] description of a [ProgramArtifact], generate random [InputValue]s for each circuit parameter. +/// +/// Use the `dictionary` to draw values from for numeric types. +pub(super) fn arb_input_map( + abi: &Abi, + dictionary: &HashSet, +) -> BoxedStrategy { + let values: Vec<_> = abi + .parameters + .iter() + .map(|param| (Just(param.name.clone()), arb_value_from_abi_type(¶m.typ, dictionary))) + .collect(); + + values + .prop_map(|values| { + let input_map: InputMap = values.into_iter().collect(); + input_map + }) + .boxed() +} diff --git a/tooling/fuzzer/src/strategies/uint.rs b/tooling/fuzzer/src/strategies/uint.rs new file mode 100644 index 00000000000..402e6559752 --- /dev/null +++ b/tooling/fuzzer/src/strategies/uint.rs @@ -0,0 +1,104 @@ +use std::collections::HashSet; + +use acvm::{AcirField, FieldElement}; +use proptest::{ + strategy::{NewTree, Strategy}, + test_runner::TestRunner, +}; +use rand::Rng; + +type BinarySearch = proptest::num::u128::BinarySearch; + +/// Value tree for unsigned ints (up to u128). +/// The strategy combines 2 different strategies, each assigned a specific weight: +/// 1. Generate purely random value in a range. This will first choose bit size uniformly (up `bits` +/// param). Then generate a value for this bit size. +/// 2. Generate a random value around the edges (+/- 3 around 0 and max possible value) +#[derive(Debug)] +pub struct UintStrategy { + /// Bit size of uint (e.g. 64) + bits: usize, + /// A set of fixtures to be generated + fixtures: Vec, + /// The weight for edge cases (+/- 3 around 0 and max possible value) + edge_weight: usize, + /// The weight for fixtures + fixtures_weight: usize, + /// The weight for purely random values + random_weight: usize, +} + +impl UintStrategy { + /// Create a new strategy. + /// # Arguments + /// * `bits` - Size of uint in bits + /// * `fixtures` - Set of `FieldElements` representing values which the fuzzer weight towards testing. + pub fn new(bits: usize, fixtures: &HashSet) -> Self { + Self { + bits, + // We can only consider the fixtures which fit into the bit width. + fixtures: fixtures.iter().filter(|f| f.num_bits() <= bits as u32).copied().collect(), + edge_weight: 10usize, + fixtures_weight: 40usize, + random_weight: 50usize, + } + } + + /// Generate random numbers starting from near 0 or the maximum of the range. + fn generate_edge_tree(&self, runner: &mut TestRunner) -> NewTree { + let rng = runner.rng(); + // Choose if we want values around 0 or max + let is_min = rng.gen_bool(0.5); + let offset = rng.gen_range(0..4); + let start = if is_min { offset } else { self.type_max().saturating_sub(offset) }; + Ok(BinarySearch::new(start)) + } + + /// Pick a random `FieldElement` from the `fixtures` as a starting point for + /// generating random numbers. + fn generate_fixtures_tree(&self, runner: &mut TestRunner) -> NewTree { + // generate random cases if there's no fixtures + if self.fixtures.is_empty() { + return self.generate_random_tree(runner); + } + + // Generate value tree from fixture. + let fixture = &self.fixtures[runner.rng().gen_range(0..self.fixtures.len())]; + + Ok(BinarySearch::new(fixture.to_u128())) + } + + /// Generate random values between 0 and the MAX with the given bit width. + fn generate_random_tree(&self, runner: &mut TestRunner) -> NewTree { + let rng = runner.rng(); + let start = rng.gen_range(0..=self.type_max()); + + Ok(BinarySearch::new(start)) + } + + /// Maximum integer that fits in the given bit width. + fn type_max(&self) -> u128 { + if self.bits < 128 { + (1 << self.bits) - 1 + } else { + u128::MAX + } + } +} + +impl Strategy for UintStrategy { + type Tree = BinarySearch; + type Value = u128; + + /// Pick randomly from the 3 available strategies for generating unsigned integers. + fn new_tree(&self, runner: &mut TestRunner) -> NewTree { + let total_weight = self.random_weight + self.fixtures_weight + self.edge_weight; + let bias = runner.rng().gen_range(0..total_weight); + // randomly select one of 3 strategies + match bias { + x if x < self.edge_weight => self.generate_edge_tree(runner), + x if x < self.edge_weight + self.fixtures_weight => self.generate_fixtures_tree(runner), + _ => self.generate_random_tree(runner), + } + } +} diff --git a/tooling/fuzzer/src/types.rs b/tooling/fuzzer/src/types.rs new file mode 100644 index 00000000000..dbd4ba94ec1 --- /dev/null +++ b/tooling/fuzzer/src/types.rs @@ -0,0 +1,42 @@ +use noirc_abi::InputMap; + +type CounterExample = InputMap; + +/// The outcome of a fuzz test +#[derive(Debug)] +pub struct FuzzTestResult { + /// Whether the test case was successful. This means that the program executed + /// properly, or that there was a constraint failure and that the test was expected to fail + /// (has the `should_fail` attribute) + pub success: bool, + + /// If there was a constraint failure, this field will be populated. Note that the test can + /// still be successful (i.e self.success == true) when it's expected to fail. + pub reason: Option, + + /// Minimal reproduction test case for failing fuzz tests + pub counterexample: Option, +} + +/// Returned by a single fuzz in the case of a successful run +#[derive(Debug)] +pub struct CaseOutcome { + /// Data of a single fuzz test case + pub case: InputMap, +} + +/// Returned by a single fuzz when a counterexample has been discovered +#[derive(Debug)] +pub struct CounterExampleOutcome { + /// Minimal reproduction test case for failing test + pub counterexample: CounterExample, + /// The status of the call + pub exit_reason: String, +} + +/// Outcome of a single fuzz +#[derive(Debug)] +pub enum FuzzOutcome { + Case(CaseOutcome), + CounterExample(CounterExampleOutcome), +} diff --git a/tooling/lsp/Cargo.toml b/tooling/lsp/Cargo.toml new file mode 100644 index 00000000000..65b59552b32 --- /dev/null +++ b/tooling/lsp/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "noir_lsp" +description = "Language server for Noir" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[lints] +workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +acvm.workspace = true +codespan-lsp.workspace = true +lsp-types.workspace = true +nargo = { workspace = true, features = ["rpc"] } +nargo_fmt.workspace = true +nargo_toml.workspace = true +noirc_driver.workspace = true +noirc_errors.workspace = true +noirc_frontend.workspace = true +serde.workspace = true +serde_json.workspace = true +strum = "0.24" +tower.workspace = true +async-lsp = { workspace = true, features = ["omni-trait"] } +thiserror.workspace = true +fm.workspace = true +rayon.workspace = true +fxhash.workspace = true +convert_case = "0.6.0" + +[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies] +wasm-bindgen.workspace = true + +[dev-dependencies] +tokio = { version = "1.0", features = ["macros", "rt"] } diff --git a/tooling/lsp/src/attribute_reference_finder.rs b/tooling/lsp/src/attribute_reference_finder.rs new file mode 100644 index 00000000000..e3f31b65b46 --- /dev/null +++ b/tooling/lsp/src/attribute_reference_finder.rs @@ -0,0 +1,115 @@ +/// If the cursor is on an custom attribute, this struct will try to resolve its +/// underlying function and return a ReferenceId to it. +/// This is needed in hover and go-to-definition because when an annotation generates +/// code, that code ends up residing in the attribute definition (it ends up having the +/// attribute's span) so using the usual graph to locate what points to that location +/// will give not only the attribute function but also any type generated by it. +use std::collections::BTreeMap; + +use fm::FileId; +use noirc_errors::Span; +use noirc_frontend::{ + ast::{AttributeTarget, Visitor}, + graph::CrateId, + hir::{ + def_map::{CrateDefMap, LocalModuleId, ModuleId}, + resolution::import::resolve_import, + }, + node_interner::ReferenceId, + parser::ParsedSubModule, + token::MetaAttribute, + usage_tracker::UsageTracker, + ParsedModule, +}; + +use crate::modules::module_def_id_to_reference_id; + +pub(crate) struct AttributeReferenceFinder<'a> { + byte_index: usize, + /// The module ID in scope. This might change as we traverse the AST + /// if we are analyzing something inside an inline module declaration. + module_id: ModuleId, + def_maps: &'a BTreeMap, + reference_id: Option, +} + +impl<'a> AttributeReferenceFinder<'a> { + #[allow(clippy::too_many_arguments)] + pub(crate) fn new( + file: FileId, + byte_index: usize, + krate: CrateId, + def_maps: &'a BTreeMap, + ) -> Self { + // Find the module the current file belongs to + let def_map = &def_maps[&krate]; + let local_id = if let Some((module_index, _)) = + def_map.modules().iter().find(|(_, module_data)| module_data.location.file == file) + { + LocalModuleId(module_index) + } else { + def_map.root() + }; + let module_id = ModuleId { krate, local_id }; + Self { byte_index, module_id, def_maps, reference_id: None } + } + + pub(crate) fn find(&mut self, parsed_module: &ParsedModule) -> Option { + parsed_module.accept(self); + + self.reference_id + } + + fn includes_span(&self, span: Span) -> bool { + span.start() as usize <= self.byte_index && self.byte_index <= span.end() as usize + } +} + +impl<'a> Visitor for AttributeReferenceFinder<'a> { + fn visit_parsed_submodule(&mut self, parsed_sub_module: &ParsedSubModule, _span: Span) -> bool { + // Switch `self.module_id` to the submodule + let previous_module_id = self.module_id; + + let def_map = &self.def_maps[&self.module_id.krate]; + if let Some(module_data) = def_map.modules().get(self.module_id.local_id.0) { + if let Some(child_module) = module_data.children.get(&parsed_sub_module.name) { + self.module_id = ModuleId { krate: self.module_id.krate, local_id: *child_module }; + } + } + + parsed_sub_module.accept_children(self); + + // Restore the old module before continuing + self.module_id = previous_module_id; + + false + } + + fn visit_meta_attribute( + &mut self, + attribute: &MetaAttribute, + _target: AttributeTarget, + ) -> bool { + if !self.includes_span(attribute.span) { + return false; + } + + let path = attribute.name.clone(); + // The path here must resolve to a function and it's a simple path (can't have turbofish) + // so it can (and must) be solved as an import. + let Ok(Some((module_def_id, _, _))) = resolve_import( + path, + self.module_id, + self.def_maps, + &mut UsageTracker::default(), + None, // references tracker + ) + .map(|result| result.namespace.values) else { + return true; + }; + + self.reference_id = Some(module_def_id_to_reference_id(module_def_id)); + + true + } +} diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs new file mode 100644 index 00000000000..97a1c7ad27b --- /dev/null +++ b/tooling/lsp/src/lib.rs @@ -0,0 +1,461 @@ +#![forbid(unsafe_code)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + +use std::{ + collections::{BTreeMap, HashMap, HashSet}, + future::Future, + ops::{self, ControlFlow}, + path::{Path, PathBuf}, + pin::Pin, + str::FromStr, + task::{self, Poll}, +}; + +use acvm::{BlackBoxFunctionSolver, FieldElement}; +use async_lsp::{ + router::Router, AnyEvent, AnyNotification, AnyRequest, ClientSocket, Error, LspService, + ResponseError, +}; +use fm::{codespan_files as files, FileManager}; +use fxhash::FxHashSet; +use lsp_types::{ + request::{ + CodeActionRequest, Completion, DocumentSymbolRequest, HoverRequest, InlayHintRequest, + PrepareRenameRequest, References, Rename, SignatureHelpRequest, + }, + CodeLens, +}; +use nargo::{ + package::{Package, PackageType}, + parse_all, + workspace::Workspace, +}; +use nargo_toml::{find_file_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_driver::{file_manager_with_stdlib, prepare_crate, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_frontend::{ + graph::{CrateGraph, CrateId, CrateName}, + hir::{ + def_map::{parse_file, CrateDefMap}, + Context, FunctionNameMatch, ParsedFiles, + }, + node_interner::NodeInterner, + parser::ParserError, + usage_tracker::UsageTracker, + ParsedModule, +}; +use rayon::prelude::*; + +use notifications::{ + on_did_change_configuration, on_did_change_text_document, on_did_close_text_document, + on_did_open_text_document, on_did_save_text_document, on_exit, on_initialized, +}; +use requests::{ + on_code_action_request, on_code_lens_request, on_completion_request, + on_document_symbol_request, on_formatting, on_goto_declaration_request, + on_goto_definition_request, on_goto_type_definition_request, on_hover_request, on_initialize, + on_inlay_hint_request, on_prepare_rename_request, on_references_request, on_rename_request, + on_shutdown, on_signature_help_request, on_test_run_request, on_tests_request, + LspInitializationOptions, +}; +use serde_json::Value as JsonValue; +use thiserror::Error; +use tower::Service; + +mod attribute_reference_finder; +mod modules; +mod notifications; +mod requests; +mod solver; +mod tests; +mod trait_impl_method_stub_generator; +mod types; +mod use_segment_positions; +mod utils; +mod visibility; + +#[cfg(test)] +mod test_utils; + +use solver::WrapperSolver; +use types::{notification, request, NargoTest, NargoTestId, Position, Range, Url}; + +#[derive(Debug, Error)] +pub enum LspError { + /// Error while Resolving Workspace. + #[error("Failed to Resolve Workspace - {0}")] + WorkspaceResolutionError(String), +} + +// State for the LSP gets implemented on this struct and is internal to the implementation +pub struct LspState { + root_path: Option, + client: ClientSocket, + solver: WrapperSolver, + open_documents_count: usize, + input_files: HashMap, + cached_lenses: HashMap>, + cached_parsed_files: HashMap))>, + workspace_cache: HashMap, + package_cache: HashMap, + options: LspInitializationOptions, + + // Tracks files that currently have errors, by package root. + files_with_errors: HashMap>, +} + +struct WorkspaceCacheData { + file_manager: FileManager, +} + +struct PackageCacheData { + crate_id: CrateId, + crate_graph: CrateGraph, + node_interner: NodeInterner, + def_maps: BTreeMap, + usage_tracker: UsageTracker, +} + +impl LspState { + fn new( + client: &ClientSocket, + solver: impl BlackBoxFunctionSolver + 'static, + ) -> Self { + Self { + client: client.clone(), + root_path: None, + solver: WrapperSolver(Box::new(solver)), + input_files: HashMap::new(), + cached_lenses: HashMap::new(), + cached_parsed_files: HashMap::new(), + workspace_cache: HashMap::new(), + package_cache: HashMap::new(), + open_documents_count: 0, + options: Default::default(), + files_with_errors: HashMap::new(), + } + } +} + +pub struct NargoLspService { + router: Router, +} + +impl NargoLspService { + pub fn new( + client: &ClientSocket, + solver: impl BlackBoxFunctionSolver + 'static, + ) -> Self { + let state = LspState::new(client, solver); + let mut router = Router::new(state); + router + .request::(on_initialize) + .request::(on_formatting) + .request::(on_shutdown) + .request::(on_code_lens_request) + .request::(on_tests_request) + .request::(on_test_run_request) + .request::(on_goto_definition_request) + .request::(on_goto_declaration_request) + .request::(on_goto_type_definition_request) + .request::(on_document_symbol_request) + .request::(on_references_request) + .request::(on_prepare_rename_request) + .request::(on_rename_request) + .request::(on_hover_request) + .request::(on_inlay_hint_request) + .request::(on_completion_request) + .request::(on_signature_help_request) + .request::(on_code_action_request) + .notification::(on_initialized) + .notification::(on_did_change_configuration) + .notification::(on_did_open_text_document) + .notification::(on_did_change_text_document) + .notification::(on_did_close_text_document) + .notification::(on_did_save_text_document) + .notification::(on_exit); + Self { router } + } +} + +// This trait implemented as a passthrough to the router, which makes +// our `NargoLspService` a normal Service as far as Tower is concerned. +impl Service for NargoLspService { + type Response = JsonValue; + type Error = ResponseError; + type Future = Pin> + Send>>; + + fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll> { + self.router.poll_ready(cx) + } + + fn call(&mut self, req: AnyRequest) -> Self::Future { + self.router.call(req) + } +} + +// This trait implemented as a passthrough to the router, which makes +// our `NargoLspService` able to accept the `async-lsp` middleware. +impl LspService for NargoLspService { + fn notify(&mut self, notification: AnyNotification) -> ControlFlow> { + self.router.notify(notification) + } + + fn emit(&mut self, event: AnyEvent) -> ControlFlow> { + self.router.emit(event) + } +} + +fn get_package_tests_in_crate( + context: &Context, + crate_id: &CrateId, + crate_name: &CrateName, +) -> Option> { + let fm = &context.file_manager; + let files = fm.as_file_map(); + let tests = + context.get_all_test_functions_in_crate_matching(crate_id, FunctionNameMatch::Anything); + + let package_tests: Vec<_> = tests + .into_iter() + .map(|(func_name, test_function)| { + let location = context.function_meta(&test_function.get_id()).name.location; + let file_id = location.file; + let file_path = fm.path(file_id).expect("file must exist to contain tests"); + let range = + byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); + let file_uri = Url::from_file_path(file_path) + .expect("Expected a valid file path that can be converted into a URI"); + + NargoTest { + id: NargoTestId::new(crate_name.clone(), func_name.clone()), + label: func_name, + uri: file_uri, + range, + } + }) + .collect(); + + if package_tests.is_empty() { + None + } else { + Some(package_tests) + } +} + +fn byte_span_to_range<'a, F: files::Files<'a> + ?Sized>( + files: &'a F, + file_id: F::FileId, + span: ops::Range, +) -> Option { + if let Ok(codespan_range) = codespan_lsp::byte_span_to_range(files, file_id, span) { + // We have to manually construct a Range because the codespan_lsp restricts lsp-types to the wrong version range + // TODO: codespan is unmaintained and we should probably subsume it. Ref https://github.com/brendanzab/codespan/issues/345 + let range = Range { + start: Position { + line: codespan_range.start.line, + character: codespan_range.start.character, + }, + end: Position { + line: codespan_range.end.line, + character: codespan_range.end.character, + }, + }; + Some(range) + } else { + None + } +} + +pub(crate) fn resolve_workspace_for_source_path(file_path: &Path) -> Result { + if let Some(toml_path) = find_file_manifest(file_path) { + match resolve_workspace_from_toml( + &toml_path, + PackageSelection::All, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + ) { + Ok(workspace) => return Ok(workspace), + Err(error) => { + eprintln!("Error while processing {:?}: {}", toml_path, error); + } + } + } + + let Some(parent_folder) = file_path + .parent() + .and_then(|f| f.file_name()) + .and_then(|file_name_os_str| file_name_os_str.to_str()) + else { + return Err(LspError::WorkspaceResolutionError(format!( + "Could not resolve parent folder for file: {:?}", + file_path + ))); + }; + + let crate_name = match CrateName::from_str(parent_folder) { + Ok(name) => name, + Err(error) => { + eprintln!("{}", error); + CrateName::from_str("root").unwrap() + } + }; + + let assumed_package = Package { + version: None, + compiler_required_version: Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + root_dir: PathBuf::from(parent_folder), + package_type: PackageType::Binary, + entry_path: PathBuf::from(file_path), + name: crate_name, + dependencies: BTreeMap::new(), + expression_width: None, + }; + let workspace = Workspace { + root_dir: PathBuf::from(parent_folder), + members: vec![assumed_package], + selected_package_index: Some(0), + is_assumed: true, + }; + Ok(workspace) +} + +pub(crate) fn workspace_package_for_file<'a>( + workspace: &'a Workspace, + file_path: &Path, +) -> Option<&'a Package> { + if workspace.is_assumed { + workspace.members.first() + } else { + workspace.members.iter().find(|package| file_path.starts_with(&package.root_dir)) + } +} + +pub(crate) fn prepare_package<'file_manager, 'parsed_files>( + file_manager: &'file_manager FileManager, + parsed_files: &'parsed_files ParsedFiles, + package: &Package, +) -> (Context<'file_manager, 'parsed_files>, CrateId) { + let (mut context, crate_id) = nargo::prepare_package(file_manager, parsed_files, package); + context.activate_lsp_mode(); + (context, crate_id) +} + +/// Prepares a package from a source string +/// This is useful for situations when we don't need dependencies +/// and just need to operate on single file. +/// +/// Use case for this is the LSP server and code lenses +/// which operate on single file and need to understand this file +/// in order to offer code lenses to the user +fn prepare_source(source: String, state: &mut LspState) -> (Context<'static, 'static>, CrateId) { + let root = Path::new(""); + let file_name = Path::new("main.nr"); + let mut file_manager = file_manager_with_stdlib(root); + file_manager.add_file_with_source(file_name, source).expect( + "Adding source buffer to file manager should never fail when file manager is empty", + ); + let parsed_files = parse_diff(&file_manager, state); + + let mut context = Context::new(file_manager, parsed_files); + context.activate_lsp_mode(); + + let root_crate_id = prepare_crate(&mut context, file_name); + + (context, root_crate_id) +} + +fn parse_diff(file_manager: &FileManager, state: &mut LspState) -> ParsedFiles { + if state.options.enable_parsing_cache { + let noir_file_hashes: Vec<_> = file_manager + .as_file_map() + .all_file_ids() + .par_bridge() + .filter_map(|&file_id| { + let file_path = file_manager.path(file_id).expect("expected file to exist"); + let file_extension = + file_path.extension().expect("expected all file paths to have an extension"); + if file_extension == "nr" { + Some(( + file_id, + file_path.to_path_buf(), + fxhash::hash(file_manager.fetch_file(file_id).expect("file must exist")), + )) + } else { + None + } + }) + .collect(); + + let cache_hits: Vec<_> = noir_file_hashes + .par_iter() + .filter_map(|(file_id, file_path, current_hash)| { + let cached_version = state.cached_parsed_files.get(file_path); + if let Some((hash, cached_parsing)) = cached_version { + if hash == current_hash { + return Some((*file_id, cached_parsing.clone())); + } + } + None + }) + .collect(); + + let cache_hits_ids: FxHashSet<_> = cache_hits.iter().map(|(file_id, _)| *file_id).collect(); + + let cache_misses: Vec<_> = noir_file_hashes + .into_par_iter() + .filter(|(id, _, _)| !cache_hits_ids.contains(id)) + .map(|(file_id, path, hash)| (file_id, path, hash, parse_file(file_manager, file_id))) + .collect(); + + cache_misses.iter().for_each(|(_, path, hash, parse_results)| { + state.cached_parsed_files.insert(path.clone(), (*hash, parse_results.clone())); + }); + + cache_misses + .into_iter() + .map(|(id, _, _, parse_results)| (id, parse_results)) + .chain(cache_hits) + .collect() + } else { + parse_all(file_manager) + } +} + +pub fn insert_all_files_for_workspace_into_file_manager( + state: &LspState, + workspace: &Workspace, + file_manager: &mut FileManager, +) { + // Source code for files we cached override those that are read from disk. + let mut overrides: HashMap<&Path, &str> = HashMap::new(); + for (path, source) in &state.input_files { + let path = path.strip_prefix("file://").unwrap(); + overrides.insert(Path::new(path), source); + } + + nargo::insert_all_files_for_workspace_into_file_manager_with_overrides( + workspace, + file_manager, + &overrides, + ); +} + +#[test] +fn prepare_package_from_source_string() { + let source = r#" + fn main() { + let x = 1; + let y = 2; + let z = x + y; + } + "#; + + let client = ClientSocket::new_closed(); + let mut state = LspState::new(&client, acvm::blackbox_solver::StubbedBlackBoxSolver::default()); + + let (mut context, crate_id) = prepare_source(source.to_string(), &mut state); + let _check_result = noirc_driver::check_crate(&mut context, crate_id, &Default::default()); + let main_func_id = context.get_main_function(&crate_id); + assert!(main_func_id.is_some()); +} diff --git a/tooling/lsp/src/modules.rs b/tooling/lsp/src/modules.rs new file mode 100644 index 00000000000..b023f3886c3 --- /dev/null +++ b/tooling/lsp/src/modules.rs @@ -0,0 +1,162 @@ +use noirc_frontend::{ + graph::{CrateId, Dependency}, + hir::def_map::{ModuleDefId, ModuleId}, + node_interner::{NodeInterner, ReferenceId}, +}; + +pub(crate) fn get_parent_module( + interner: &NodeInterner, + module_def_id: ModuleDefId, +) -> Option { + let reference_id = module_def_id_to_reference_id(module_def_id); + interner.reference_module(reference_id).copied() +} + +pub(crate) fn module_def_id_to_reference_id(module_def_id: ModuleDefId) -> ReferenceId { + match module_def_id { + ModuleDefId::ModuleId(id) => ReferenceId::Module(id), + ModuleDefId::FunctionId(id) => ReferenceId::Function(id), + ModuleDefId::TypeId(id) => ReferenceId::Struct(id), + ModuleDefId::TypeAliasId(id) => ReferenceId::Alias(id), + ModuleDefId::TraitId(id) => ReferenceId::Trait(id), + ModuleDefId::GlobalId(id) => ReferenceId::Global(id), + } +} + +/// Returns the fully-qualified path of the given `ModuleDefId` relative to `current_module_id`: +/// - If `ModuleDefId` is a module, that module's path is returned +/// - Otherwise, that item's parent module's path is returned +pub(crate) fn relative_module_full_path( + module_def_id: ModuleDefId, + current_module_id: ModuleId, + current_module_parent_id: Option, + interner: &NodeInterner, +) -> Option { + let full_path; + if let ModuleDefId::ModuleId(module_id) = module_def_id { + full_path = relative_module_id_path( + module_id, + ¤t_module_id, + current_module_parent_id, + interner, + ); + } else { + let parent_module = get_parent_module(interner, module_def_id)?; + + full_path = relative_module_id_path( + parent_module, + ¤t_module_id, + current_module_parent_id, + interner, + ); + } + Some(full_path) +} + +/// Returns the path to reach an item inside `target_module_id` from inside `current_module_id`. +/// Returns a relative path if possible. +pub(crate) fn relative_module_id_path( + target_module_id: ModuleId, + current_module_id: &ModuleId, + current_module_parent_id: Option, + interner: &NodeInterner, +) -> String { + if Some(target_module_id) == current_module_parent_id { + return "super".to_string(); + } + + let mut segments: Vec<&str> = Vec::new(); + let mut is_relative = false; + + if let Some(module_attributes) = interner.try_module_attributes(&target_module_id) { + segments.push(&module_attributes.name); + + let mut current_attributes = module_attributes; + loop { + let Some(parent_local_id) = current_attributes.parent else { + break; + }; + + let parent_module_id = + &ModuleId { krate: target_module_id.krate, local_id: parent_local_id }; + + if current_module_id == parent_module_id { + is_relative = true; + break; + } + + if current_module_parent_id == Some(*parent_module_id) { + segments.push("super"); + is_relative = true; + break; + } + + let Some(parent_attributes) = interner.try_module_attributes(parent_module_id) else { + break; + }; + + segments.push(&parent_attributes.name); + current_attributes = parent_attributes; + } + } + + if !is_relative { + // We don't record module attributes for the root module, + // so we handle that case separately + if target_module_id.krate.is_root() { + segments.push("crate"); + } + } + + segments.reverse(); + segments.join("::") +} + +pub(crate) fn module_full_path( + module: &ModuleId, + interner: &NodeInterner, + crate_id: CrateId, + crate_name: &str, + dependencies: &Vec, +) -> String { + let mut segments: Vec = Vec::new(); + + if let Some(module_attributes) = interner.try_module_attributes(module) { + segments.push(module_attributes.name.clone()); + + let mut current_attributes = module_attributes; + loop { + let Some(parent_local_id) = current_attributes.parent else { + break; + }; + + let Some(parent_attributes) = interner.try_module_attributes(&ModuleId { + krate: module.krate, + local_id: parent_local_id, + }) else { + break; + }; + + segments.push(parent_attributes.name.clone()); + current_attributes = parent_attributes; + } + } + + // We don't record module attributes for the root module, + // so we handle that case separately + if module.krate.is_root() { + if module.krate == crate_id { + segments.push(crate_name.to_string()); + } else { + for dep in dependencies { + if dep.crate_id == crate_id { + segments.push(dep.name.to_string()); + break; + } + } + } + }; + + segments.reverse(); + segments.join("::") +} diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs new file mode 100644 index 00000000000..f6fdd082d0b --- /dev/null +++ b/tooling/lsp/src/notifications/mod.rs @@ -0,0 +1,406 @@ +use std::collections::HashSet; +use std::ops::ControlFlow; +use std::path::PathBuf; + +use crate::{ + insert_all_files_for_workspace_into_file_manager, PackageCacheData, WorkspaceCacheData, +}; +use async_lsp::{ErrorCode, LanguageClient, ResponseError}; +use fm::{FileId, FileManager, FileMap}; +use fxhash::FxHashMap as HashMap; +use lsp_types::{DiagnosticRelatedInformation, DiagnosticTag, Url}; +use noirc_driver::check_crate; +use noirc_errors::reporter::CustomLabel; +use noirc_errors::{DiagnosticKind, FileDiagnostic, Location}; + +use crate::types::{ + notification, Diagnostic, DiagnosticSeverity, DidChangeConfigurationParams, + DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams, + DidSaveTextDocumentParams, InitializedParams, NargoPackageTests, PublishDiagnosticsParams, +}; + +use crate::{ + byte_span_to_range, get_package_tests_in_crate, parse_diff, resolve_workspace_for_source_path, + LspState, +}; + +pub(super) fn on_initialized( + _state: &mut LspState, + _params: InitializedParams, +) -> ControlFlow> { + ControlFlow::Continue(()) +} + +pub(super) fn on_did_change_configuration( + _state: &mut LspState, + _params: DidChangeConfigurationParams, +) -> ControlFlow> { + ControlFlow::Continue(()) +} + +pub(crate) fn on_did_open_text_document( + state: &mut LspState, + params: DidOpenTextDocumentParams, +) -> ControlFlow> { + state.input_files.insert(params.text_document.uri.to_string(), params.text_document.text); + + let document_uri = params.text_document.uri; + let output_diagnostics = true; + + match process_workspace_for_noir_document(state, document_uri, output_diagnostics) { + Ok(_) => { + state.open_documents_count += 1; + ControlFlow::Continue(()) + } + Err(err) => ControlFlow::Break(Err(err)), + } +} + +pub(super) fn on_did_change_text_document( + state: &mut LspState, + params: DidChangeTextDocumentParams, +) -> ControlFlow> { + let text = params.content_changes.into_iter().next().unwrap().text; + state.input_files.insert(params.text_document.uri.to_string(), text.clone()); + + let document_uri = params.text_document.uri; + let output_diagnostics = false; + + match process_workspace_for_noir_document(state, document_uri, output_diagnostics) { + Ok(_) => ControlFlow::Continue(()), + Err(err) => ControlFlow::Break(Err(err)), + } +} + +pub(super) fn on_did_close_text_document( + state: &mut LspState, + params: DidCloseTextDocumentParams, +) -> ControlFlow> { + state.input_files.remove(¶ms.text_document.uri.to_string()); + state.cached_lenses.remove(¶ms.text_document.uri.to_string()); + + state.open_documents_count -= 1; + + if state.open_documents_count == 0 { + state.package_cache.clear(); + state.workspace_cache.clear(); + } + + let document_uri = params.text_document.uri; + let output_diagnostics = false; + + match process_workspace_for_noir_document(state, document_uri, output_diagnostics) { + Ok(_) => ControlFlow::Continue(()), + Err(err) => ControlFlow::Break(Err(err)), + } +} + +pub(super) fn on_did_save_text_document( + state: &mut LspState, + params: DidSaveTextDocumentParams, +) -> ControlFlow> { + let document_uri = params.text_document.uri; + let output_diagnostics = true; + + match process_workspace_for_noir_document(state, document_uri, output_diagnostics) { + Ok(_) => ControlFlow::Continue(()), + Err(err) => ControlFlow::Break(Err(err)), + } +} + +// Given a Noir document, find the workspace it's contained in (an assumed workspace is created if +// it's only contained in a package), then type-checks the workspace's packages, +// caching code lenses and type definitions, and notifying about compilation errors. +pub(crate) fn process_workspace_for_noir_document( + state: &mut LspState, + document_uri: Url, + output_diagnostics: bool, +) -> Result<(), async_lsp::Error> { + let file_path = document_uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + let workspace = resolve_workspace_for_source_path(&file_path).map_err(|lsp_error| { + ResponseError::new(ErrorCode::REQUEST_FAILED, lsp_error.to_string()) + })?; + + let mut workspace_file_manager = workspace.new_file_manager(); + + insert_all_files_for_workspace_into_file_manager( + state, + &workspace, + &mut workspace_file_manager, + ); + + let parsed_files = parse_diff(&workspace_file_manager, state); + + for package in workspace.into_iter() { + let (mut context, crate_id) = + crate::prepare_package(&workspace_file_manager, &parsed_files, package); + + let file_diagnostics = match check_crate(&mut context, crate_id, &Default::default()) { + Ok(((), warnings)) => warnings, + Err(errors_and_warnings) => errors_and_warnings, + }; + + // We don't add test headings for a package if it contains no `#[test]` functions + if let Some(tests) = get_package_tests_in_crate(&context, &crate_id, &package.name) { + let _ = state.client.notify::(NargoPackageTests { + package: package.name.to_string(), + tests, + }); + } + + let collected_lenses = crate::requests::collect_lenses_for_package( + &context, + crate_id, + &workspace, + package, + Some(&file_path), + ); + state.cached_lenses.insert(document_uri.to_string(), collected_lenses); + state.package_cache.insert( + package.root_dir.clone(), + PackageCacheData { + crate_id, + crate_graph: context.crate_graph, + node_interner: context.def_interner, + def_maps: context.def_maps, + usage_tracker: context.usage_tracker, + }, + ); + + let fm = &context.file_manager; + let files = fm.as_file_map(); + + if output_diagnostics { + publish_diagnostics(state, &package.root_dir, files, fm, file_diagnostics); + } + } + + state.workspace_cache.insert( + workspace.root_dir.clone(), + WorkspaceCacheData { file_manager: workspace_file_manager }, + ); + + Ok(()) +} + +fn publish_diagnostics( + state: &mut LspState, + package_root_dir: &PathBuf, + files: &FileMap, + fm: &FileManager, + file_diagnostics: Vec, +) { + let mut diagnostics_per_url: HashMap> = HashMap::default(); + + for file_diagnostic in file_diagnostics.into_iter() { + let file_id = file_diagnostic.file_id; + let path = fm.path(file_id).expect("file must exist to have emitted diagnostic"); + if let Ok(uri) = Url::from_file_path(path) { + if let Some(diagnostic) = + file_diagnostic_to_diagnostic(file_diagnostic, files, fm, uri.clone()) + { + diagnostics_per_url.entry(uri).or_default().push(diagnostic); + } + } + } + + let new_files_with_errors: HashSet<_> = diagnostics_per_url.keys().cloned().collect(); + + for (uri, diagnostics) in diagnostics_per_url { + let _ = state.client.publish_diagnostics(PublishDiagnosticsParams { + uri, + version: None, + diagnostics, + }); + } + + // For files that previously had errors but no longer have errors we still need to publish empty diagnostics + if let Some(old_files_with_errors) = state.files_with_errors.get(package_root_dir) { + for uri in old_files_with_errors.difference(&new_files_with_errors) { + let _ = state.client.publish_diagnostics(PublishDiagnosticsParams { + uri: uri.clone(), + version: None, + diagnostics: vec![], + }); + } + } + + // Remember which files currently have errors, for next time + state.files_with_errors.insert(package_root_dir.clone(), new_files_with_errors); +} + +fn file_diagnostic_to_diagnostic( + file_diagnostic: FileDiagnostic, + files: &FileMap, + fm: &FileManager, + uri: Url, +) -> Option { + let file_id = file_diagnostic.file_id; + let diagnostic = file_diagnostic.diagnostic; + + if diagnostic.secondaries.is_empty() { + return None; + } + + let span = diagnostic.secondaries.first().unwrap().span; + let range = byte_span_to_range(files, file_id, span.into())?; + + let severity = match diagnostic.kind { + DiagnosticKind::Error => DiagnosticSeverity::ERROR, + DiagnosticKind::Warning => DiagnosticSeverity::WARNING, + DiagnosticKind::Info => DiagnosticSeverity::INFORMATION, + DiagnosticKind::Bug => DiagnosticSeverity::WARNING, + }; + + let mut tags = Vec::new(); + if diagnostic.unnecessary { + tags.push(DiagnosticTag::UNNECESSARY); + } + if diagnostic.deprecated { + tags.push(DiagnosticTag::DEPRECATED); + } + + let secondaries = diagnostic + .secondaries + .into_iter() + .filter_map(|secondary| secondary_to_related_information(secondary, file_id, files, fm)); + let notes = diagnostic.notes.into_iter().map(|message| DiagnosticRelatedInformation { + location: lsp_types::Location { uri: uri.clone(), range }, + message, + }); + let call_stack = diagnostic + .call_stack + .into_iter() + .filter_map(|frame| call_stack_frame_to_related_information(frame, files, fm)); + let related_information: Vec<_> = secondaries.chain(notes).chain(call_stack).collect(); + + Some(Diagnostic { + range, + severity: Some(severity), + message: diagnostic.message, + tags: if tags.is_empty() { None } else { Some(tags) }, + related_information: if related_information.is_empty() { + None + } else { + Some(related_information) + }, + ..Default::default() + }) +} + +fn secondary_to_related_information( + secondary: CustomLabel, + file_id: FileId, + files: &FileMap, + fm: &FileManager, +) -> Option { + let secondary_file = secondary.file.unwrap_or(file_id); + let path = fm.path(secondary_file)?; + let uri = Url::from_file_path(path).ok()?; + let range = byte_span_to_range(files, file_id, secondary.span.into())?; + let message = secondary.message; + Some(DiagnosticRelatedInformation { location: lsp_types::Location { uri, range }, message }) +} + +fn call_stack_frame_to_related_information( + frame: Location, + files: &FileMap, + fm: &FileManager, +) -> Option { + let path = fm.path(frame.file)?; + let uri = Url::from_file_path(path).ok()?; + let range = byte_span_to_range(files, frame.file, frame.span.into())?; + Some(DiagnosticRelatedInformation { + location: lsp_types::Location { uri, range }, + message: "Error originated here".to_string(), + }) +} + +pub(super) fn on_exit( + _state: &mut LspState, + _params: (), +) -> ControlFlow> { + ControlFlow::Continue(()) +} + +#[cfg(test)] +mod notification_tests { + use crate::test_utils; + + use super::*; + use lsp_types::{ + InlayHintLabel, InlayHintParams, Position, Range, TextDocumentContentChangeEvent, + TextDocumentIdentifier, TextDocumentItem, VersionedTextDocumentIdentifier, + WorkDoneProgressParams, + }; + use tokio::test; + + #[test] + async fn test_caches_open_files() { + let (mut state, noir_text_document) = test_utils::init_lsp_server("inlay_hints").await; + + // Open the document, fake the text to be empty + on_did_open_text_document( + &mut state, + DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: noir_text_document.clone(), + language_id: "noir".to_string(), + version: 0, + text: "".to_string(), + }, + }, + ); + + // Fake the text to change to "global a = 1;" + on_did_change_text_document( + &mut state, + DidChangeTextDocumentParams { + text_document: VersionedTextDocumentIdentifier { + uri: noir_text_document.clone(), + version: 1, + }, + content_changes: vec![TextDocumentContentChangeEvent { + range: None, + range_length: None, + // Should get an inlay hint for ": bool" after "a" + text: "global a = true;".to_string(), + }], + }, + ); + + // Get inlay hints. These should now be relative to the changed text, + // not the saved file's text. + let inlay_hints = crate::requests::on_inlay_hint_request( + &mut state, + InlayHintParams { + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + text_document: TextDocumentIdentifier { uri: noir_text_document }, + range: Range { + start: Position { line: 0, character: 0 }, + end: Position { line: 1, character: 0 }, + }, + }, + ) + .await + .expect("Could not execute on_inlay_hint_request") + .unwrap(); + + assert_eq!(inlay_hints.len(), 1); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 0, character: 8 }); + + if let InlayHintLabel::LabelParts(labels) = &inlay_hint.label { + assert_eq!(labels.len(), 2); + assert_eq!(labels[0].value, ": "); + assert_eq!(labels[0].location, None); + assert_eq!(labels[1].value, "bool"); + } else { + panic!("Expected InlayHintLabel::LabelParts, got {:?}", inlay_hint.label); + } + } +} diff --git a/tooling/lsp/src/requests/code_action.rs b/tooling/lsp/src/requests/code_action.rs new file mode 100644 index 00000000000..24ed327393d --- /dev/null +++ b/tooling/lsp/src/requests/code_action.rs @@ -0,0 +1,293 @@ +use std::{ + collections::{BTreeMap, HashMap}, + future::{self, Future}, + ops::Range, +}; + +use async_lsp::ResponseError; +use fm::{FileId, FileMap, PathString}; +use lsp_types::{ + CodeAction, CodeActionKind, CodeActionOrCommand, CodeActionParams, CodeActionResponse, + TextDocumentPositionParams, TextEdit, Url, WorkspaceEdit, +}; +use noirc_errors::Span; +use noirc_frontend::{ + ast::{ + CallExpression, ConstructorExpression, ItemVisibility, MethodCallExpression, NoirTraitImpl, + Path, UseTree, Visitor, + }, + graph::CrateId, + hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}, + node_interner::NodeInterner, + usage_tracker::UsageTracker, +}; +use noirc_frontend::{ + parser::{Item, ItemKind, ParsedSubModule}, + ParsedModule, +}; + +use crate::{use_segment_positions::UseSegmentPositions, utils, LspState}; + +use super::{process_request, to_lsp_location}; + +mod fill_struct_fields; +mod implement_missing_members; +mod import_or_qualify; +mod import_trait; +mod remove_bang_from_call; +mod remove_unused_import; +mod tests; + +pub(crate) fn on_code_action_request( + state: &mut LspState, + params: CodeActionParams, +) -> impl Future, ResponseError>> { + let uri = params.text_document.clone().uri; + let position = params.range.start; + let text_document_position_params = + TextDocumentPositionParams { text_document: params.text_document, position }; + + let result = process_request(state, text_document_position_params, |args| { + let path = PathString::from_path(uri.to_file_path().unwrap()); + args.files.get_file_id(&path).and_then(|file_id| { + utils::range_to_byte_span(args.files, file_id, ¶ms.range).and_then(|byte_range| { + let file = args.files.get_file(file_id).unwrap(); + let source = file.source(); + let (parsed_module, _errors) = noirc_frontend::parse_program(source); + + let mut finder = CodeActionFinder::new( + uri, + args.files, + file_id, + source, + byte_range, + args.crate_id, + args.def_maps, + args.interner, + args.usage_tracker, + ); + finder.find(&parsed_module) + }) + }) + }); + future::ready(result) +} + +struct CodeActionFinder<'a> { + uri: Url, + files: &'a FileMap, + file: FileId, + source: &'a str, + lines: Vec<&'a str>, + byte_range: Range, + /// The module ID in scope. This might change as we traverse the AST + /// if we are analyzing something inside an inline module declaration. + module_id: ModuleId, + def_maps: &'a BTreeMap, + interner: &'a NodeInterner, + usage_tracker: &'a UsageTracker, + /// How many nested `mod` we are in deep + nesting: usize, + /// The line where an auto_import must be inserted + auto_import_line: usize, + use_segment_positions: UseSegmentPositions, + /// Text edits for the "Remove all unused imports" code action + unused_imports_text_edits: Vec, + code_actions: Vec, +} + +impl<'a> CodeActionFinder<'a> { + #[allow(clippy::too_many_arguments)] + fn new( + uri: Url, + files: &'a FileMap, + file: FileId, + source: &'a str, + byte_range: Range, + krate: CrateId, + def_maps: &'a BTreeMap, + interner: &'a NodeInterner, + usage_tracker: &'a UsageTracker, + ) -> Self { + // Find the module the current file belongs to + let def_map = &def_maps[&krate]; + let local_id = if let Some((module_index, _)) = + def_map.modules().iter().find(|(_, module_data)| module_data.location.file == file) + { + LocalModuleId(module_index) + } else { + def_map.root() + }; + let module_id = ModuleId { krate, local_id }; + Self { + uri, + files, + file, + source, + lines: source.lines().collect(), + byte_range, + module_id, + def_maps, + interner, + usage_tracker, + nesting: 0, + auto_import_line: 0, + use_segment_positions: UseSegmentPositions::default(), + unused_imports_text_edits: vec![], + code_actions: vec![], + } + } + + fn find(&mut self, parsed_module: &ParsedModule) -> Option { + parsed_module.accept(self); + + if self.code_actions.is_empty() { + return None; + } + + // We also suggest a single "Remove all the unused imports" code action that combines all of the + // "Remove unused imports" (similar to Rust Analyzer) + if self.unused_imports_text_edits.len() > 1 { + let text_edits = std::mem::take(&mut self.unused_imports_text_edits); + let code_action = self.new_quick_fix_multiple_edits( + "Remove all the unused imports".to_string(), + text_edits, + ); + self.code_actions.push(code_action); + } + + let mut code_actions = std::mem::take(&mut self.code_actions); + code_actions.sort_by_key(|code_action| code_action.title.clone()); + + Some(code_actions.into_iter().map(CodeActionOrCommand::CodeAction).collect()) + } + + fn new_quick_fix(&self, title: String, text_edit: TextEdit) -> CodeAction { + self.new_quick_fix_multiple_edits(title, vec![text_edit]) + } + + fn new_quick_fix_multiple_edits(&self, title: String, text_edits: Vec) -> CodeAction { + let mut changes = HashMap::new(); + changes.insert(self.uri.clone(), text_edits); + + let workspace_edit = WorkspaceEdit { + changes: Some(changes), + document_changes: None, + change_annotations: None, + }; + + CodeAction { + title, + kind: Some(CodeActionKind::QUICKFIX), + diagnostics: None, + edit: Some(workspace_edit), + command: None, + is_preferred: None, + disabled: None, + data: None, + } + } + + fn includes_span(&self, span: Span) -> bool { + let byte_range_span = Span::from(self.byte_range.start as u32..self.byte_range.end as u32); + span.intersects(&byte_range_span) + } +} + +impl<'a> Visitor for CodeActionFinder<'a> { + fn visit_item(&mut self, item: &Item) -> bool { + if let ItemKind::Import(use_tree, _) = &item.kind { + if let Some(lsp_location) = to_lsp_location(self.files, self.file, item.span) { + self.auto_import_line = (lsp_location.range.end.line + 1) as usize; + } + self.use_segment_positions.add(use_tree); + } + + self.includes_span(item.span) + } + + fn visit_parsed_submodule(&mut self, parsed_sub_module: &ParsedSubModule, span: Span) -> bool { + // Switch `self.module_id` to the submodule + let previous_module_id = self.module_id; + + let def_map = &self.def_maps[&self.module_id.krate]; + let Some(module_data) = def_map.modules().get(self.module_id.local_id.0) else { + return false; + }; + if let Some(child_module) = module_data.children.get(&parsed_sub_module.name) { + self.module_id = ModuleId { krate: self.module_id.krate, local_id: *child_module }; + } + + let old_auto_import_line = self.auto_import_line; + self.nesting += 1; + + if let Some(lsp_location) = to_lsp_location(self.files, self.file, span) { + self.auto_import_line = (lsp_location.range.start.line + 1) as usize; + } + + parsed_sub_module.contents.accept(self); + + // Restore the old module before continuing + self.module_id = previous_module_id; + self.nesting -= 1; + self.auto_import_line = old_auto_import_line; + + false + } + + fn visit_import(&mut self, use_tree: &UseTree, span: Span, visibility: ItemVisibility) -> bool { + self.remove_unused_import(use_tree, visibility, span); + + true + } + + fn visit_path(&mut self, path: &Path) { + self.import_or_qualify(path); + } + + fn visit_constructor_expression( + &mut self, + constructor: &ConstructorExpression, + span: Span, + ) -> bool { + self.fill_struct_fields(constructor, span); + + true + } + + fn visit_noir_trait_impl(&mut self, noir_trait_impl: &NoirTraitImpl, span: Span) -> bool { + self.implement_missing_members(noir_trait_impl, span); + + true + } + + fn visit_call_expression(&mut self, call: &CallExpression, span: Span) -> bool { + if !self.includes_span(span) { + return false; + } + + if call.is_macro_call { + self.remove_bang_from_call(call.func.span); + } + + true + } + + fn visit_method_call_expression( + &mut self, + method_call: &MethodCallExpression, + span: Span, + ) -> bool { + if !self.includes_span(span) { + return false; + } + + if method_call.is_macro_call { + self.remove_bang_from_call(method_call.method_name.span()); + } + + self.import_trait_in_method_call(method_call); + + true + } +} diff --git a/tooling/lsp/src/requests/code_action/fill_struct_fields.rs b/tooling/lsp/src/requests/code_action/fill_struct_fields.rs new file mode 100644 index 00000000000..739f0bf4a21 --- /dev/null +++ b/tooling/lsp/src/requests/code_action/fill_struct_fields.rs @@ -0,0 +1,313 @@ +use lsp_types::TextEdit; +use noirc_errors::{Location, Span}; +use noirc_frontend::{ + ast::{ConstructorExpression, UnresolvedTypeData}, + node_interner::ReferenceId, +}; + +use crate::byte_span_to_range; + +use super::CodeActionFinder; + +impl<'a> CodeActionFinder<'a> { + pub(super) fn fill_struct_fields(&mut self, constructor: &ConstructorExpression, span: Span) { + if !self.includes_span(span) { + return; + } + + let UnresolvedTypeData::Named(path, _, _) = &constructor.typ.typ else { + return; + }; + + let location = Location::new(path.span, self.file); + let Some(ReferenceId::Struct(struct_id)) = self.interner.find_referenced(location) else { + return; + }; + + let struct_type = self.interner.get_struct(struct_id); + let struct_type = struct_type.borrow(); + + // First get all of the struct's fields + let mut fields = struct_type.get_fields_as_written(); + + // Remove the ones that already exists in the constructor + for (constructor_field, _) in &constructor.fields { + fields.retain(|field| field.name.0.contents != constructor_field.0.contents); + } + + if fields.is_empty() { + return; + } + + // Some fields are missing. Let's suggest a quick fix that adds them. + let bytes = self.source.as_bytes(); + let right_brace_index = span.end() as usize - 1; + let mut index = right_brace_index - 1; + while bytes[index].is_ascii_whitespace() { + index -= 1; + } + + let char_before_right_brace = bytes[index] as char; + + index += 1; + + let Some(range) = byte_span_to_range(self.files, self.file, index..index) else { + return; + }; + + // If the constructor spans multiple lines, we'll add the new fields in new lines too. + // Otherwise we'll add all the fields in a single line. + let constructor_range = + byte_span_to_range(self.files, self.file, span.start() as usize..span.end() as usize); + + // If it's multiline, find out the indent of the beginning line: we'll add new fields + // with that indent "plus one" (4 more spaces). + let line_indent = if let Some(constructor_range) = constructor_range { + if constructor_range.start.line == constructor_range.end.line { + None + } else { + let line = self.lines[constructor_range.start.line as usize]; + let whitespace_bytes = + line.bytes().take_while(|byte| byte.is_ascii_whitespace()).count(); + Some(whitespace_bytes) + } + } else { + None + }; + let line_indent = line_indent.map(|indent| " ".repeat(indent + 4)); + + let on_whitespace = bytes[index].is_ascii_whitespace(); + + let mut new_text = String::new(); + + // Add a comma if there's not a trailing one (if there are existing fields) + if !constructor.fields.is_empty() && char_before_right_brace != ',' { + new_text.push(','); + } + + // Add space or newline depending on whether it's multiline or not + if let Some(line_indent) = &line_indent { + new_text.push('\n'); + new_text.push_str(line_indent); + } else if !on_whitespace || constructor.fields.is_empty() { + new_text.push(' '); + } + + for (index, field) in fields.iter().enumerate() { + if index > 0 { + new_text.push(','); + if let Some(line_indent) = &line_indent { + new_text.push('\n'); + new_text.push_str(line_indent); + } else { + new_text.push(' '); + } + } + new_text.push_str(&field.name.0.contents); + new_text.push_str(": ()"); + } + + if !bytes[right_brace_index - 1].is_ascii_whitespace() { + new_text.push(' '); + } + + let title = "Fill struct fields".to_string(); + let text_edit = TextEdit { range, new_text }; + let code_action = self.new_quick_fix(title, text_edit); + self.code_actions.push(code_action); + } +} + +#[cfg(test)] +mod tests { + use tokio::test; + + use crate::requests::code_action::tests::assert_code_action; + + #[test] + async fn test_fill_struct_fields_code_action_no_space() { + let title = "Fill struct fields"; + + let src = r#" + struct Foo { + one: Field, + two: Field, + } + + fn main() { + Foo {>|<} + } + "#; + + let expected = r#" + struct Foo { + one: Field, + two: Field, + } + + fn main() { + Foo { one: (), two: () } + } + "#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_fill_struct_fields_code_action_space() { + let title = "Fill struct fields"; + + let src = r#" + struct Foo { + one: Field, + two: Field, + } + + fn main() { + Foo { >|<} + } + "#; + + let expected = r#" + struct Foo { + one: Field, + two: Field, + } + + fn main() { + Foo { one: (), two: () } + } + "#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_fill_struct_fields_code_action_some_fields() { + let title = "Fill struct fields"; + + let src = r#" + struct Foo { + one: Field, + two: Field, + three: Field, + } + + fn main() { + Foo { two: 1>|<} + } + "#; + + let expected = r#" + struct Foo { + one: Field, + two: Field, + three: Field, + } + + fn main() { + Foo { two: 1, one: (), three: () } + } + "#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_fill_struct_fields_code_action_some_fields_trailing_comma() { + let title = "Fill struct fields"; + + let src = r#" + struct Foo { + one: Field, + two: Field, + three: Field, + } + + fn main() { + Foo { two: 1,>|<} + } + "#; + + let expected = r#" + struct Foo { + one: Field, + two: Field, + three: Field, + } + + fn main() { + Foo { two: 1, one: (), three: () } + } + "#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_fill_struct_fields_code_action_multiline_empty() { + let title = "Fill struct fields"; + + let src = r#" + struct Foo { + one: Field, + two: Field, + } + + fn main() { + Foo {>|< + } + } + "#; + + let expected = r#" + struct Foo { + one: Field, + two: Field, + } + + fn main() { + Foo { + one: (), + two: () + } + } + "#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_fill_struct_fields_code_action_multiline_some_fields() { + let title = "Fill struct fields"; + + let src = r#" + struct Foo { + one: Field, + two: Field, + } + + fn main() { + Foo {>|< + one: 1, + } + } + "#; + + let expected = r#" + struct Foo { + one: Field, + two: Field, + } + + fn main() { + Foo { + one: 1, + two: () + } + } + "#; + + assert_code_action(title, src, expected).await; + } +} diff --git a/tooling/lsp/src/requests/code_action/implement_missing_members.rs b/tooling/lsp/src/requests/code_action/implement_missing_members.rs new file mode 100644 index 00000000000..1cd181966a2 --- /dev/null +++ b/tooling/lsp/src/requests/code_action/implement_missing_members.rs @@ -0,0 +1,439 @@ +use std::collections::HashMap; + +use lsp_types::TextEdit; +use noirc_errors::{Location, Span}; +use noirc_frontend::{ + ast::{NoirTraitImpl, TraitImplItemKind, UnresolvedTypeData}, + node_interner::ReferenceId, +}; + +use crate::{byte_span_to_range, trait_impl_method_stub_generator::TraitImplMethodStubGenerator}; + +use super::CodeActionFinder; + +impl<'a> CodeActionFinder<'a> { + pub(super) fn implement_missing_members( + &mut self, + noir_trait_impl: &NoirTraitImpl, + span: Span, + ) { + if !self.includes_span(span) { + return; + } + + let location = Location::new(noir_trait_impl.trait_name.span(), self.file); + let Some(ReferenceId::Trait(trait_id)) = self.interner.find_referenced(location) else { + return; + }; + + let trait_ = self.interner.get_trait(trait_id); + + // Get all methods + let mut method_ids = trait_.method_ids.clone(); + + // Also get all associated types + let mut associated_types = HashMap::new(); + for associated_type in &trait_.associated_types { + associated_types.insert(associated_type.name.as_ref(), associated_type); + } + + // Remove the ones that already are implemented + for item in &noir_trait_impl.items { + match &item.item.kind { + TraitImplItemKind::Function(noir_function) => { + method_ids.remove(noir_function.name()); + } + TraitImplItemKind::Constant(..) => (), + TraitImplItemKind::Type { name, alias } => { + if let UnresolvedTypeData::Unspecified = alias.typ { + continue; + } + associated_types.remove(&name.0.contents); + } + } + } + + // Also remove default methods + for trait_function in &trait_.methods { + if trait_function.default_impl.is_some() { + method_ids.remove(&trait_function.name.0.contents); + } + } + + if method_ids.is_empty() && associated_types.is_empty() { + return; + } + + let bytes = self.source.as_bytes(); + let right_brace_index = span.end() as usize - 1; + + // Let's find out the indent + let mut cursor = right_brace_index - 1; + while cursor > 0 { + let c = bytes[cursor] as char; + if c == '\n' { + break; + } + if !c.is_whitespace() { + break; + } + cursor -= 1; + } + let cursor_char = bytes[cursor] as char; + + let indent = if cursor_char == '\n' { right_brace_index - cursor - 1 } else { 0 }; + let indent_string = " ".repeat(indent + 4); + + let index = cursor + 1; + + let Some(range) = byte_span_to_range(self.files, self.file, index..index) else { + return; + }; + + let mut method_ids: Vec<_> = method_ids.iter().collect(); + method_ids.sort_by_key(|(name, _)| *name); + + let mut stubs = Vec::new(); + + for (name, _) in associated_types { + stubs.push(format!("{}type {};\n", indent_string, name)); + } + + for (name, func_id) in method_ids { + let func_meta = self.interner.function_meta(func_id); + let modifiers = self.interner.function_modifiers(func_id); + + let mut generator = TraitImplMethodStubGenerator::new( + name, + func_meta, + modifiers, + trait_, + noir_trait_impl, + self.interner, + self.def_maps, + self.module_id, + indent + 4, + ); + generator.set_body(format!("panic(f\"Implement {}\")", name)); + + let stub = generator.generate(); + stubs.push(stub); + } + + let mut new_text = stubs.join("\n"); + if cursor_char != '\n' { + new_text.insert(0, '\n'); + } + + let title = "Implement missing members".to_string(); + let text_edit = TextEdit { range, new_text }; + let code_action = self.new_quick_fix(title, text_edit); + self.code_actions.push(code_action); + } +} + +#[cfg(test)] +mod tests { + use tokio::test; + + use crate::requests::code_action::tests::assert_code_action; + + #[test] + async fn test_add_missing_impl_members_simple() { + let title = "Implement missing members"; + + let src = r#" +trait Trait { + fn foo(x: i32) -> i32; + fn bar() {} +} + +struct Foo {} + +impl Tra>| i32; + fn bar() {} +} + +struct Foo {} + +impl Trait for Foo { + fn foo(x: i32) -> i32 { + panic(f"Implement foo") + } +}"#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_add_missing_impl_members_multiple_with_self_type() { + let title = "Implement missing members"; + + let src = r#" +trait Trait { + fn bar(self) -> Self; + fn foo(x: i32) -> i32; +} + +struct Foo {} + +impl Tra>| Self; + fn foo(x: i32) -> i32; +} + +struct Foo {} + +impl Trait for Foo { + fn bar(self) -> Self { + panic(f"Implement bar") + } + + fn foo(x: i32) -> i32 { + panic(f"Implement foo") + } +}"#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_add_missing_impl_members_qualify_type() { + let title = "Implement missing members"; + + let src = r#" +mod moo { + struct Moo {} + + trait Trait { + fn foo(x: Moo); + } +} + +struct Foo {} + +use moo::Trait; + +impl Tra>|| { + fn foo(x: T) -> [T; N] where M: Bar; +} + +struct Foo {} + +impl Tra>| for Foo { +}"#; + + let expected = r#" +trait Bar {} + +trait Trait { + fn foo(x: T) -> [T; N] where M: Bar; +} + +struct Foo {} + +impl Trait<[U]> for Foo { + fn foo(x: [U]) -> [[U]; N] where M: Bar { + panic(f"Implement foo") + } +}"#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_add_missing_impl_members_associated_types() { + let title = "Implement missing members"; + + let src = r#" +trait Trait { + type Elem; + + fn foo(x: Self::Elem) -> [Self::Elem]; +} + +struct Foo {} + +impl Trait>|< for Foo { +}"#; + + let expected = r#" +trait Trait { + type Elem; + + fn foo(x: Self::Elem) -> [Self::Elem]; +} + +struct Foo {} + +impl Trait for Foo { + type Elem; + + fn foo(x: Self::Elem) -> [Self::Elem] { + panic(f"Implement foo") + } +}"#; + + assert_code_action(title, src, expected).await; + } + + #[test] + async fn test_add_missing_impl_members_nested() { + let title = "Implement missing members"; + + let src = r#" +mod moo { + trait Trait { + fn foo(); + fn bar(); + } + + struct Foo {} + + impl Tra>|| CodeActionFinder<'a> { + pub(super) fn import_or_qualify(&mut self, path: &Path) { + if path.segments.len() != 1 { + return; + } + + let ident = &path.segments[0].ident; + if !self.includes_span(ident.span()) { + return; + } + + let location = Location::new(ident.span(), self.file); + if self.interner.find_referenced(location).is_some() { + return; + } + + let current_module_parent_id = self.module_id.parent(self.def_maps); + + // The Path doesn't resolve to anything so it means it's an error and maybe we + // can suggest an import or to fully-qualify the path. + for (name, entries) in self.interner.get_auto_import_names() { + if name != &ident.0.contents { + continue; + } + + for (module_def_id, visibility, defining_module) in entries { + if !module_def_id_is_visible( + *module_def_id, + self.module_id, + *visibility, + *defining_module, + self.interner, + self.def_maps, + ) { + continue; + } + + let module_full_path = if let Some(defining_module) = defining_module { + relative_module_id_path( + *defining_module, + &self.module_id, + current_module_parent_id, + self.interner, + ) + } else { + let Some(module_full_path) = relative_module_full_path( + *module_def_id, + self.module_id, + current_module_parent_id, + self.interner, + ) else { + continue; + }; + module_full_path + }; + + let full_path = if defining_module.is_some() + || !matches!(module_def_id, ModuleDefId::ModuleId(..)) + { + format!("{}::{}", module_full_path, name) + } else { + module_full_path.clone() + }; + + let qualify_prefix = if let ModuleDefId::ModuleId(..) = module_def_id { + let mut segments: Vec<_> = module_full_path.split("::").collect(); + segments.pop(); + segments.join("::") + } else { + module_full_path + }; + + self.push_import_code_action(&full_path); + self.push_qualify_code_action(ident, &qualify_prefix, &full_path); + } + } + } + + fn push_import_code_action(&mut self, full_path: &str) { + let title = format!("Import {}", full_path); + + let text_edits = use_completion_item_additional_text_edits( + UseCompletionItemAdditionTextEditsRequest { + full_path, + files: self.files, + file: self.file, + lines: &self.lines, + nesting: self.nesting, + auto_import_line: self.auto_import_line, + }, + &self.use_segment_positions, + ); + + let code_action = self.new_quick_fix_multiple_edits(title, text_edits); + self.code_actions.push(code_action); + } + + fn push_qualify_code_action(&mut self, ident: &Ident, prefix: &str, full_path: &str) { + let Some(range) = byte_span_to_range( + self.files, + self.file, + ident.span().start() as usize..ident.span().start() as usize, + ) else { + return; + }; + + let title = format!("Qualify as {}", full_path); + let text_edit = TextEdit { range, new_text: format!("{}::", prefix) }; + + let code_action = self.new_quick_fix(title, text_edit); + self.code_actions.push(code_action); + } +} + +#[cfg(test)] +mod tests { + use tokio::test; + + use crate::requests::code_action::tests::assert_code_action; + + #[test] + async fn test_qualify_code_action_for_struct() { + let title = "Qualify as foo::bar::SomeTypeInBar"; + + let src = r#" + mod foo { + pub mod bar { + pub struct SomeTypeInBar {} + } + } + + fn foo(x: SomeType>|||||| CodeActionFinder<'a> { + pub(super) fn import_trait_in_method_call(&mut self, method_call: &MethodCallExpression) { + // First see if the method name already points to a function. + let name_location = Location::new(method_call.method_name.span(), self.file); + if let Some(ReferenceId::Function(func_id)) = self.interner.find_referenced(name_location) { + // If yes, it could be that the compiler is issuing a warning because there's + // only one possible trait that the method could be coming from, but it's not imported + let func_meta = self.interner.function_meta(&func_id); + let Some(trait_impl_id) = func_meta.trait_impl else { + return; + }; + + let trait_impl = self.interner.get_trait_implementation(trait_impl_id); + let trait_id = trait_impl.borrow().trait_id; + let trait_ = self.interner.get_trait(trait_id); + + // Check if the trait is currently imported. If so, no need to suggest anything + let module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + if !module_data.scope().find_name(&trait_.name).is_none() { + return; + } + + self.push_import_trait_code_action(trait_); + return; + } + + // Find out the type of the object + let object_location = Location::new(method_call.object.span, self.file); + let Some(typ) = self.interner.type_at_location(object_location) else { + return; + }; + + for (func_id, trait_id) in + self.interner.lookup_trait_methods(&typ, &method_call.method_name.0.contents, true) + { + let visibility = self.interner.function_modifiers(&func_id).visibility; + if !trait_member_is_visible(trait_id, visibility, self.module_id, self.def_maps) { + continue; + } + + let trait_ = self.interner.get_trait(trait_id); + self.push_import_trait_code_action(trait_); + } + } + + fn push_import_trait_code_action(&mut self, trait_: &Trait) { + let trait_id = trait_.id; + + let module_def_id = ModuleDefId::TraitId(trait_id); + let current_module_parent_id = self.module_id.parent(self.def_maps); + let Some(module_full_path) = relative_module_full_path( + module_def_id, + self.module_id, + current_module_parent_id, + self.interner, + ) else { + return; + }; + let full_path = format!("{}::{}", module_full_path, trait_.name); + + let title = format!("Import {}", full_path); + + let text_edits = use_completion_item_additional_text_edits( + UseCompletionItemAdditionTextEditsRequest { + full_path: &full_path, + files: self.files, + file: self.file, + lines: &self.lines, + nesting: self.nesting, + auto_import_line: self.auto_import_line, + }, + &self.use_segment_positions, + ); + + let code_action = self.new_quick_fix_multiple_edits(title, text_edits); + self.code_actions.push(code_action); + } +} + +#[cfg(test)] +mod tests { + use tokio::test; + + use crate::requests::code_action::tests::assert_code_action; + + #[test] + async fn test_import_trait_in_method_call_when_one_option_but_not_in_scope() { + let title = "Import moo::Foo"; + + let src = r#"mod moo { + pub trait Foo { + fn foobar(self); + } + + impl Foo for Field { + fn foobar(self) {} + } +} + +fn main() { + let x: Field = 1; + x.foo>||| CodeActionFinder<'a> { + pub(super) fn remove_bang_from_call(&mut self, span: Span) { + // If we can't find the referenced function, there's nothing we can do + let Some(ReferenceId::Function(func_id)) = + self.interner.find_referenced(Location::new(span, self.file)) + else { + return; + }; + + // If the return type is Quoted, all is good + let func_meta = self.interner.function_meta(&func_id); + if let Type::Quoted(QuotedType::Quoted) = func_meta.return_type() { + return; + } + + // The `!` comes right after the name + let byte_span = span.end() as usize..span.end() as usize + 1; + let Some(range) = byte_span_to_range(self.files, self.file, byte_span) else { + return; + }; + + let title = "Remove `!` from call".to_string(); + let text_edit = TextEdit { range, new_text: "".to_string() }; + + let code_action = self.new_quick_fix(title, text_edit); + self.code_actions.push(code_action); + } +} + +#[cfg(test)] +mod tests { + use tokio::test; + + use crate::requests::code_action::tests::assert_code_action; + + #[test] + async fn test_removes_bang_from_call() { + let title = "Remove `!` from call"; + + let src = r#" + fn foo() {} + + fn main() { + fo>|| CodeActionFinder<'a> { + pub(super) fn remove_unused_import( + &mut self, + use_tree: &UseTree, + visibility: ItemVisibility, + span: Span, + ) { + if !self.includes_span(span) { + return; + } + + let Some(unused_items) = self.usage_tracker.unused_items().get(&self.module_id) else { + return; + }; + + if unused_items.is_empty() { + return; + } + + if has_unused_import(use_tree, unused_items) { + let byte_span = span.start() as usize..span.end() as usize; + let Some(range) = byte_span_to_range(self.files, self.file, byte_span) else { + return; + }; + + let (use_tree, removed_count) = use_tree_without_unused_import(use_tree, unused_items); + let (title, new_text) = match use_tree { + Some(use_tree) => ( + if removed_count == 1 { + "Remove unused import".to_string() + } else { + "Remove unused imports".to_string() + }, + use_tree_to_string(use_tree, visibility, self.nesting), + ), + None => ("Remove the whole `use` item".to_string(), "".to_string()), + }; + + let text_edit = TextEdit { range, new_text }; + self.unused_imports_text_edits.push(text_edit.clone()); + + let code_action = self.new_quick_fix(title, text_edit); + self.code_actions.push(code_action); + } + } +} + +fn has_unused_import(use_tree: &UseTree, unused_items: &HashMap) -> bool { + match &use_tree.kind { + UseTreeKind::Path(name, alias) => { + let ident = alias.as_ref().unwrap_or(name); + unused_items.contains_key(ident) + } + UseTreeKind::List(use_trees) => { + use_trees.iter().any(|use_tree| has_unused_import(use_tree, unused_items)) + } + } +} + +/// Returns a new `UseTree` with all the unused imports removed, and the number of removed imports. +fn use_tree_without_unused_import( + use_tree: &UseTree, + unused_items: &HashMap, +) -> (Option, usize) { + match &use_tree.kind { + UseTreeKind::Path(name, alias) => { + let ident = alias.as_ref().unwrap_or(name); + if unused_items.contains_key(ident) { + (None, 1) + } else { + (Some(use_tree.clone()), 0) + } + } + UseTreeKind::List(use_trees) => { + let mut new_use_trees: Vec = Vec::new(); + let mut total_count = 0; + + for use_tree in use_trees { + let (new_use_tree, count) = use_tree_without_unused_import(use_tree, unused_items); + if let Some(new_use_tree) = new_use_tree { + new_use_trees.push(new_use_tree); + } + total_count += count; + } + + let new_use_tree = if new_use_trees.is_empty() { + None + } else if new_use_trees.len() == 1 { + let new_use_tree = new_use_trees.remove(0); + + let mut prefix = use_tree.prefix.clone(); + prefix.segments.extend(new_use_tree.prefix.segments); + + Some(UseTree { prefix, kind: new_use_tree.kind, span: use_tree.span }) + } else { + Some(UseTree { + prefix: use_tree.prefix.clone(), + kind: UseTreeKind::List(new_use_trees), + span: use_tree.span, + }) + }; + + (new_use_tree, total_count) + } + } +} + +fn use_tree_to_string(use_tree: UseTree, visibility: ItemVisibility, nesting: usize) -> String { + // We are going to use the formatter to format the use tree + let source = if visibility == ItemVisibility::Private { + format!("use {};", &use_tree) + } else { + format!("{} use {};", visibility, &use_tree) + }; + let parsed_module = ParsedModule { + items: vec![Item { + kind: ItemKind::Import(use_tree, visibility), + span: Span::from(0..source.len() as u32), + doc_comments: Vec::new(), + }], + inner_doc_comments: Vec::new(), + }; + + // Adjust the max width according to the current nesting + let mut config = nargo_fmt::Config::default(); + config.max_width -= nesting * 4; + + let string = nargo_fmt::format(&source, parsed_module, &config); + + let string = if nesting > 0 && string.contains('\n') { + // If the import is nested in a module, we just formatted it without indents so we need to add them. + let indent = " ".repeat(nesting * 4); + string.lines().map(|line| format!("{}{}", indent, line)).collect::>().join("\n") + } else { + string + }; + string.trim().to_string() +} + +#[cfg(test)] +mod tests { + use tokio::test; + + use crate::requests::code_action::tests::assert_code_action; + + #[test] + async fn test_removes_entire_unused_import_at_top_level() { + let title = "Remove the whole `use` item"; + + let src = r#" + mod moo { + pub fn foo() {} + } + use moo::fo>||||| CodeActionResponse { + let (mut state, noir_text_document) = test_utils::init_lsp_server("document_symbol").await; + + let (line, column) = src + .lines() + .enumerate() + .find_map(|(line_index, line)| line.find(">|<").map(|char_index| (line_index, char_index))) + .expect("Expected to find one >|< in the source code"); + + let src = src.replace(">|<", ""); + + on_did_open_text_document( + &mut state, + DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: noir_text_document.clone(), + language_id: "noir".to_string(), + version: 0, + text: src.to_string(), + }, + }, + ); + + let position = Position { line: line as u32, character: column as u32 }; + + on_code_action_request( + &mut state, + CodeActionParams { + text_document: TextDocumentIdentifier { uri: noir_text_document }, + range: Range { start: position, end: position }, + context: CodeActionContext { diagnostics: Vec::new(), only: None, trigger_kind: None }, + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + partial_result_params: PartialResultParams { partial_result_token: None }, + }, + ) + .await + .expect("Could not execute on_code_action_request") + .expect("Expected to get a CodeActionResponse, got None") +} + +pub(crate) async fn assert_code_action(title: &str, src: &str, expected: &str) { + let actions = get_code_action(src).await; + let action = actions + .iter() + .filter_map(|action| { + if let CodeActionOrCommand::CodeAction(action) = action { + if action.title == title { + Some(action) + } else { + None + } + } else { + None + } + }) + .next() + .expect("Couldn't find an action with the given title"); + + let workspace_edit = action.edit.as_ref().unwrap(); + let text_edits = workspace_edit.changes.as_ref().unwrap().iter().next().unwrap().1; + + let result = apply_text_edits(&src.replace(">|<", ""), text_edits); + if result != expected { + println!("Expected:\n```\n{}\n```\n\nGot:\n```\n{}\n```", expected, result); + assert_eq!(result, expected); + } +} diff --git a/tooling/lsp/src/requests/code_lens_request.rs b/tooling/lsp/src/requests/code_lens_request.rs new file mode 100644 index 00000000000..0c1877c156d --- /dev/null +++ b/tooling/lsp/src/requests/code_lens_request.rs @@ -0,0 +1,217 @@ +use std::future::{self, Future}; + +use async_lsp::{ErrorCode, ResponseError}; + +use nargo::{package::Package, workspace::Workspace}; +use noirc_driver::check_crate; +use noirc_frontend::hir::FunctionNameMatch; + +use crate::{ + byte_span_to_range, prepare_source, resolve_workspace_for_source_path, + types::{CodeLens, CodeLensParams, CodeLensResult, Command}, + LspState, +}; + +const ARROW: &str = "▶\u{fe0e}"; +const TEST_COMMAND: &str = "nargo.test"; +const TEST_CODELENS_TITLE: &str = "Run Test"; +const COMPILE_COMMAND: &str = "nargo.compile"; +const COMPILE_CODELENS_TITLE: &str = "Compile"; +const INFO_COMMAND: &str = "nargo.info"; +const INFO_CODELENS_TITLE: &str = "Info"; +const EXECUTE_COMMAND: &str = "nargo.execute"; +const EXECUTE_CODELENS_TITLE: &str = "Execute"; +const DEBUG_COMMAND: &str = "nargo.debug.dap"; +const DEBUG_CODELENS_TITLE: &str = "Debug"; + +fn with_arrow(title: &str) -> String { + format!("{ARROW} {title}") +} + +fn package_selection_args(workspace: &Workspace, package: &Package) -> Vec { + vec![ + "--program-dir".into(), + workspace.root_dir.display().to_string().into(), + "--package".into(), + package.name.to_string().into(), + ] +} + +pub(crate) fn on_code_lens_request( + state: &mut LspState, + params: CodeLensParams, +) -> impl Future> { + future::ready(on_code_lens_request_inner(state, params)) +} + +fn on_code_lens_request_inner( + state: &mut LspState, + params: CodeLensParams, +) -> Result { + let file_path = params.text_document.uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + if let Some(collected_lenses) = state.cached_lenses.get(¶ms.text_document.uri.to_string()) { + return Ok(Some(collected_lenses.clone())); + } + + let source_string = std::fs::read_to_string(&file_path).map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not read file from disk") + })?; + + let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); + + let package = crate::workspace_package_for_file(&workspace, &file_path).ok_or_else(|| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find package for file") + })?; + + 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, &Default::default()); + + let collected_lenses = + collect_lenses_for_package(&context, crate_id, &workspace, package, None); + + if collected_lenses.is_empty() { + state.cached_lenses.remove(¶ms.text_document.uri.to_string()); + Ok(None) + } else { + state + .cached_lenses + .insert(params.text_document.uri.to_string().clone(), collected_lenses.clone()); + Ok(Some(collected_lenses)) + } +} + +pub(crate) fn collect_lenses_for_package( + context: &noirc_frontend::hir::Context, + crate_id: noirc_frontend::graph::CrateId, + workspace: &Workspace, + package: &Package, + file_path: Option<&std::path::PathBuf>, +) -> Vec { + let mut lenses: Vec = vec![]; + let fm = &context.file_manager; + let files = fm.as_file_map(); + let tests = + context.get_all_test_functions_in_crate_matching(&crate_id, FunctionNameMatch::Anything); + for (func_name, test_function) in tests { + let location = context.function_meta(&test_function.get_id()).name.location; + let file_id = location.file; + + // Ignore diagnostics for any file that wasn't the file we saved + // TODO: In the future, we could create "related" diagnostics for these files + if let Some(file_path) = file_path { + if fm.path(file_id).expect("file must exist to contain tests") != *file_path { + continue; + } + } + + let range = byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); + + let test_command = Command { + title: with_arrow(TEST_CODELENS_TITLE), + command: TEST_COMMAND.into(), + arguments: Some( + [ + package_selection_args(workspace, package), + vec!["--exact".into(), "--show-output".into(), func_name.into()], + ] + .concat(), + ), + }; + + let test_lens = CodeLens { range, command: Some(test_command), data: None }; + + lenses.push(test_lens); + } + + if package.is_binary() { + if let Some(main_func_id) = context.get_main_function(&crate_id) { + let location = context.function_meta(&main_func_id).name.location; + let file_id = location.file; + + // Ignore diagnostics for any file that wasn't the file we saved + // TODO: In the future, we could create "related" diagnostics for these files + if let Some(file_path) = file_path { + if fm.path(file_id).expect("file must exist to contain `main` function") + != *file_path + { + return lenses; + } + } + + let range = + byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); + + let compile_command = Command { + title: with_arrow(COMPILE_CODELENS_TITLE), + command: COMPILE_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; + + lenses.push(compile_lens); + + let internal_command_lenses = [ + (INFO_CODELENS_TITLE, INFO_COMMAND), + (EXECUTE_CODELENS_TITLE, EXECUTE_COMMAND), + (DEBUG_CODELENS_TITLE, DEBUG_COMMAND), + ] + .map(|(title, command)| { + let command = Command { + title: title.to_string(), + command: command.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + CodeLens { range, command: Some(command), data: None } + }); + + lenses.append(&mut Vec::from(internal_command_lenses)); + } + } + + if package.is_contract() { + // Currently not looking to deduplicate this since we don't have a clear decision on if the Contract stuff is staying + for contract in context.get_all_contracts(&crate_id) { + let location = contract.location; + let file_id = location.file; + + // Ignore diagnostics for any file that wasn't the file we saved + // TODO: In the future, we could create "related" diagnostics for these files + if let Some(file_path) = file_path { + if fm.path(file_id).expect("file must exist to contain a contract") != *file_path { + continue; + } + } + + let range = + byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); + + let compile_command = Command { + title: with_arrow(COMPILE_CODELENS_TITLE), + command: COMPILE_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; + + lenses.push(compile_lens); + + let info_command = Command { + title: INFO_CODELENS_TITLE.to_string(), + command: INFO_COMMAND.into(), + arguments: Some(package_selection_args(workspace, package)), + }; + + let info_lens = CodeLens { range, command: Some(info_command), data: None }; + + lenses.push(info_lens); + } + } + + lenses +} diff --git a/tooling/lsp/src/requests/completion.rs b/tooling/lsp/src/requests/completion.rs new file mode 100644 index 00000000000..219103388bc --- /dev/null +++ b/tooling/lsp/src/requests/completion.rs @@ -0,0 +1,1898 @@ +use std::{ + collections::{BTreeMap, HashMap, HashSet}, + future::{self, Future}, +}; + +use async_lsp::ResponseError; +use completion_items::{ + field_completion_item, simple_completion_item, snippet_completion_item, + trait_impl_method_completion_item, +}; +use convert_case::{Case, Casing}; +use fm::{FileId, FileMap, PathString}; +use kinds::{FunctionCompletionKind, FunctionKind, RequestedItems}; +use lsp_types::{CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse}; +use noirc_errors::{Location, Span}; +use noirc_frontend::{ + ast::{ + AsTraitPath, AttributeTarget, BlockExpression, CallExpression, ConstructorExpression, + Expression, ExpressionKind, ForLoopStatement, GenericTypeArgs, Ident, IfExpression, + IntegerBitSize, ItemVisibility, LValue, Lambda, LetStatement, MemberAccessExpression, + MethodCallExpression, NoirFunction, NoirStruct, NoirTraitImpl, Path, PathKind, Pattern, + Signedness, Statement, TraitBound, TraitImplItemKind, TypeImpl, TypePath, + UnresolvedGeneric, UnresolvedGenerics, UnresolvedType, UnresolvedTypeData, + UnresolvedTypeExpression, UseTree, UseTreeKind, Visitor, + }, + graph::{CrateId, Dependency}, + hir::{ + def_map::{CrateDefMap, LocalModuleId, ModuleDefId, ModuleId}, + resolution::visibility::{ + item_in_module_is_visible, method_call_is_visible, struct_member_is_visible, + trait_member_is_visible, + }, + }, + hir_def::traits::Trait, + node_interner::{FuncId, NodeInterner, ReferenceId, StructId}, + parser::{Item, ItemKind, ParsedSubModule}, + token::{MetaAttribute, Token, Tokens}, + Kind, ParsedModule, StructType, Type, TypeBinding, +}; +use sort_text::underscore_sort_text; + +use crate::{ + requests::to_lsp_location, trait_impl_method_stub_generator::TraitImplMethodStubGenerator, + use_segment_positions::UseSegmentPositions, utils, LspState, +}; + +use super::process_request; + +mod auto_import; +mod builtins; +mod completion_items; +mod kinds; +mod sort_text; +mod tests; + +pub(crate) fn on_completion_request( + state: &mut LspState, + params: CompletionParams, +) -> impl Future, ResponseError>> { + let uri = params.text_document_position.clone().text_document.uri; + + let result = process_request(state, params.text_document_position.clone(), |args| { + let path = PathString::from_path(uri.to_file_path().unwrap()); + args.files.get_file_id(&path).and_then(|file_id| { + utils::position_to_byte_index( + args.files, + file_id, + ¶ms.text_document_position.position, + ) + .and_then(|byte_index| { + let file = args.files.get_file(file_id).unwrap(); + let source = file.source(); + let byte = source.as_bytes().get(byte_index - 1).copied(); + let (parsed_module, _errors) = noirc_frontend::parse_program(source); + + let mut finder = NodeFinder::new( + args.files, + file_id, + source, + byte_index, + byte, + args.crate_id, + args.def_maps, + args.dependencies, + args.interner, + ); + finder.find(&parsed_module) + }) + }) + }); + future::ready(result) +} + +struct NodeFinder<'a> { + files: &'a FileMap, + file: FileId, + source: &'a str, + lines: Vec<&'a str>, + byte_index: usize, + byte: Option, + /// The module ID in scope. This might change as we traverse the AST + /// if we are analyzing something inside an inline module declaration. + module_id: ModuleId, + def_maps: &'a BTreeMap, + dependencies: &'a Vec, + interner: &'a NodeInterner, + /// Completion items we find along the way. + completion_items: Vec, + /// Local variables in the current scope, mapped to their locations. + /// As we traverse the AST, we collect local variables. + local_variables: HashMap, + /// Type parameters in the current scope. These are collected when entering + /// a struct, a function, etc., and cleared afterwards. + type_parameters: HashSet, + /// ModuleDefIds we already suggested, so we don't offer these for auto-import. + suggested_module_def_ids: HashSet, + /// How many nested `mod` we are in deep + nesting: usize, + /// The line where an auto_import must be inserted + auto_import_line: usize, + use_segment_positions: UseSegmentPositions, + self_type: Option, + in_comptime: bool, + /// The function we are in, if any + func_id: Option, +} + +impl<'a> NodeFinder<'a> { + #[allow(clippy::too_many_arguments)] + fn new( + files: &'a FileMap, + file: FileId, + source: &'a str, + byte_index: usize, + byte: Option, + krate: CrateId, + def_maps: &'a BTreeMap, + dependencies: &'a Vec, + interner: &'a NodeInterner, + ) -> Self { + // Find the module the current file belongs to + let def_map = &def_maps[&krate]; + let local_id = if let Some((module_index, _)) = + def_map.modules().iter().find(|(_, module_data)| module_data.location.file == file) + { + LocalModuleId(module_index) + } else { + def_map.root() + }; + let module_id = ModuleId { krate, local_id }; + Self { + files, + file, + source, + lines: source.lines().collect(), + byte_index, + byte, + module_id, + def_maps, + dependencies, + interner, + completion_items: Vec::new(), + local_variables: HashMap::new(), + type_parameters: HashSet::new(), + suggested_module_def_ids: HashSet::new(), + nesting: 0, + auto_import_line: 0, + use_segment_positions: UseSegmentPositions::default(), + self_type: None, + in_comptime: false, + func_id: None, + } + } + + fn find(&mut self, parsed_module: &ParsedModule) -> Option { + parsed_module.accept(self); + + if self.completion_items.is_empty() { + None + } else { + let mut items = std::mem::take(&mut self.completion_items); + + // Show items that start with underscore last in the list + for item in items.iter_mut() { + if item.label.starts_with('_') { + item.sort_text = Some(underscore_sort_text()); + } + } + + Some(CompletionResponse::Array(items)) + } + } + + fn complete_constructor_field_name(&mut self, constructor_expression: &ConstructorExpression) { + let span = if let UnresolvedTypeData::Named(path, _, _) = &constructor_expression.typ.typ { + path.last_ident().span() + } else { + constructor_expression.typ.span + }; + + let location = Location::new(span, self.file); + let Some(ReferenceId::Struct(struct_id)) = self.interner.find_referenced(location) else { + return; + }; + + let struct_type = self.interner.get_struct(struct_id); + let struct_type = struct_type.borrow(); + + // First get all of the struct's fields + let mut fields: Vec<_> = + struct_type.get_fields_as_written().into_iter().enumerate().collect(); + + // Remove the ones that already exists in the constructor + for (used_name, _) in &constructor_expression.fields { + fields.retain(|(_, field)| field.name.0.contents != used_name.0.contents); + } + + let self_prefix = false; + for (field_index, field) in &fields { + self.completion_items.push(self.struct_field_completion_item( + &field.name.0.contents, + &field.typ, + struct_type.id, + *field_index, + self_prefix, + )); + } + } + + fn find_in_path(&mut self, path: &Path, requested_items: RequestedItems) { + self.find_in_path_impl(path, requested_items, false); + } + + fn find_in_path_impl( + &mut self, + path: &Path, + requested_items: RequestedItems, + mut in_the_middle: bool, + ) { + if !self.includes_span(path.span) { + return; + } + + let after_colons = self.byte == Some(b':'); + + let mut idents: Vec = Vec::new(); + + // Find in which ident we are in, and in which part of it + // (it could be that we are completing in the middle of an ident) + for segment in &path.segments { + let ident = &segment.ident; + + // Check if we are at the end of the ident + if self.byte_index == ident.span().end() as usize { + idents.push(ident.clone()); + break; + } + + // Check if we are in the middle of an ident + if self.includes_span(ident.span()) { + // If so, take the substring and push that as the list of idents + // we'll do autocompletion for + let offset = self.byte_index - ident.span().start() as usize; + let substring = ident.0.contents[0..offset].to_string(); + let ident = Ident::new( + substring, + Span::from(ident.span().start()..ident.span().start() + offset as u32), + ); + idents.push(ident); + in_the_middle = true; + break; + } + + idents.push(ident.clone()); + + // Stop if the cursor is right after this ident and '::' + if after_colons && self.byte_index == ident.span().end() as usize + 2 { + break; + } + } + + if idents.len() < path.segments.len() { + in_the_middle = true; + } + + let prefix; + let at_root; + + if after_colons { + prefix = String::new(); + at_root = false; + } else { + prefix = idents.pop().unwrap().to_string(); + at_root = idents.is_empty(); + } + + let prefix = prefix.to_case(Case::Snake); + + let is_single_segment = !after_colons && idents.is_empty() && path.kind == PathKind::Plain; + let module_id; + + // When completing in the middle of an ident, we don't want to complete + // with function parameters because there might already be function parameters, + // and in the middle of a path it leads to code that won't compile + let function_completion_kind = if in_the_middle { + FunctionCompletionKind::Name + } else { + FunctionCompletionKind::NameAndParameters + }; + + if idents.is_empty() { + module_id = self.module_id; + } else { + let Some(module_def_id) = self.resolve_path(idents) else { + return; + }; + + match module_def_id { + ModuleDefId::ModuleId(id) => module_id = id, + ModuleDefId::TypeId(struct_id) => { + let struct_type = self.interner.get_struct(struct_id); + self.complete_type_methods( + &Type::Struct(struct_type, vec![]), + &prefix, + FunctionKind::Any, + function_completion_kind, + false, // self_prefix + ); + return; + } + ModuleDefId::FunctionId(_) => { + // There's nothing inside a function + return; + } + ModuleDefId::TypeAliasId(type_alias_id) => { + let type_alias = self.interner.get_type_alias(type_alias_id); + let type_alias = type_alias.borrow(); + self.complete_type_methods( + &type_alias.typ, + &prefix, + FunctionKind::Any, + function_completion_kind, + false, // self_prefix + ); + return; + } + ModuleDefId::TraitId(trait_id) => { + let trait_ = self.interner.get_trait(trait_id); + self.complete_trait_methods( + trait_, + &prefix, + FunctionKind::Any, + function_completion_kind, + ); + return; + } + ModuleDefId::GlobalId(_) => return, + } + } + + self.complete_in_module( + module_id, + &prefix, + path.kind, + at_root, + function_completion_kind, + requested_items, + ); + + if is_single_segment { + match requested_items { + RequestedItems::AnyItems => { + self.local_variables_completion(&prefix); + self.builtin_functions_completion(&prefix, function_completion_kind); + self.builtin_values_completion(&prefix); + self.builtin_types_completion(&prefix); + self.type_parameters_completion(&prefix); + if let Some(self_type) = &self.self_type { + let self_prefix = true; + self.complete_type_fields_and_methods( + &self_type.clone(), + &prefix, + function_completion_kind, + self_prefix, + ); + } + } + RequestedItems::OnlyTypes => { + self.builtin_types_completion(&prefix); + self.type_parameters_completion(&prefix); + } + RequestedItems::OnlyTraits | RequestedItems::OnlyAttributeFunctions(..) => (), + } + self.complete_auto_imports(&prefix, requested_items, function_completion_kind); + } + } + + fn local_variables_completion(&mut self, prefix: &str) { + for (name, span) in &self.local_variables { + if name_matches(name, prefix) { + let location = Location::new(*span, self.file); + let description = if let Some(ReferenceId::Local(definition_id)) = + self.interner.reference_at_location(location) + { + let typ = self.interner.definition_type(definition_id); + Some(typ.to_string()) + } else { + None + }; + + self.completion_items.push(simple_completion_item( + name, + CompletionItemKind::VARIABLE, + description, + )); + } + } + } + + fn type_parameters_completion(&mut self, prefix: &str) { + for name in &self.type_parameters { + if name_matches(name, prefix) { + self.completion_items.push(simple_completion_item( + name, + CompletionItemKind::TYPE_PARAMETER, + None, + )); + } + } + } + + fn find_in_use_tree(&mut self, use_tree: &UseTree, prefixes: &mut Vec) { + match &use_tree.kind { + UseTreeKind::Path(ident, alias) => { + prefixes.push(use_tree.prefix.clone()); + self.find_in_use_tree_path(prefixes, ident, alias); + prefixes.pop(); + } + UseTreeKind::List(use_trees) => { + prefixes.push(use_tree.prefix.clone()); + for use_tree in use_trees { + self.find_in_use_tree(use_tree, prefixes); + } + prefixes.pop(); + } + } + } + + fn find_in_use_tree_path( + &mut self, + prefixes: &Vec, + ident: &Ident, + alias: &Option, + ) { + if let Some(_alias) = alias { + // Won't handle completion if there's an alias (for now) + return; + } + + let after_colons = self.byte == Some(b':'); + let at_ident_end = self.byte_index == ident.span().end() as usize; + let at_ident_colons_end = + after_colons && self.byte_index - 2 == ident.span().end() as usize; + + if !(at_ident_end || at_ident_colons_end) { + return; + } + + let path_kind = prefixes[0].kind; + + let mut segments: Vec = Vec::new(); + for prefix in prefixes { + for segment in &prefix.segments { + segments.push(segment.ident.clone()); + } + } + + let function_completion_kind = FunctionCompletionKind::Name; + let requested_items = RequestedItems::AnyItems; + + if after_colons { + // We are right after "::" + segments.push(ident.clone()); + + if let Some(module_id) = self.resolve_module(segments) { + let prefix = ""; + let at_root = false; + self.complete_in_module( + module_id, + prefix, + path_kind, + at_root, + function_completion_kind, + requested_items, + ); + }; + } else { + // We are right after the last segment + let prefix = ident.to_string().to_case(Case::Snake); + if segments.is_empty() { + let at_root = true; + self.complete_in_module( + self.module_id, + &prefix, + path_kind, + at_root, + function_completion_kind, + requested_items, + ); + } else if let Some(module_id) = self.resolve_module(segments) { + let at_root = false; + self.complete_in_module( + module_id, + &prefix, + path_kind, + at_root, + function_completion_kind, + requested_items, + ); + } + } + } + + fn collect_local_variables(&mut self, pattern: &Pattern) { + match pattern { + Pattern::Identifier(ident) => { + self.local_variables.insert(ident.to_string(), ident.span()); + } + Pattern::Mutable(pattern, _, _) => self.collect_local_variables(pattern), + Pattern::Tuple(patterns, _) => { + for pattern in patterns { + self.collect_local_variables(pattern); + } + } + Pattern::Struct(_, patterns, _) => { + for (_, pattern) in patterns { + self.collect_local_variables(pattern); + } + } + Pattern::Interned(..) => (), + } + } + + fn collect_type_parameters_in_generics(&mut self, generics: &UnresolvedGenerics) { + for generic in generics { + self.collect_type_parameters_in_generic(generic); + } + } + + fn collect_type_parameters_in_generic(&mut self, generic: &UnresolvedGeneric) { + match generic { + UnresolvedGeneric::Variable(ident) => { + self.type_parameters.insert(ident.to_string()); + } + UnresolvedGeneric::Numeric { ident, typ: _ } => { + self.type_parameters.insert(ident.to_string()); + } + UnresolvedGeneric::Resolved(..) => (), + }; + } + + fn complete_type_fields_and_methods( + &mut self, + typ: &Type, + prefix: &str, + function_completion_kind: FunctionCompletionKind, + self_prefix: bool, + ) { + let typ = &typ; + match typ { + Type::Struct(struct_type, generics) => { + self.complete_struct_fields(&struct_type.borrow(), generics, prefix, self_prefix); + } + Type::MutableReference(typ) => { + return self.complete_type_fields_and_methods( + typ, + prefix, + function_completion_kind, + self_prefix, + ); + } + Type::Alias(type_alias, _) => { + let type_alias = type_alias.borrow(); + return self.complete_type_fields_and_methods( + &type_alias.typ, + prefix, + function_completion_kind, + self_prefix, + ); + } + Type::CheckedCast { to, .. } => { + return self.complete_type_fields_and_methods( + to, + prefix, + function_completion_kind, + self_prefix, + ); + } + Type::Tuple(types) => { + self.complete_tuple_fields(types, self_prefix); + } + Type::TypeVariable(var) | Type::NamedGeneric(var, _) => { + if let TypeBinding::Bound(ref typ) = &*var.borrow() { + return self.complete_type_fields_and_methods( + typ, + prefix, + function_completion_kind, + self_prefix, + ); + } + } + Type::FieldElement + | Type::Array(_, _) + | Type::Slice(_) + | Type::Integer(_, _) + | Type::Bool + | Type::String(_) + | Type::FmtString(_, _) + | Type::Unit + | Type::TraitAsType(_, _, _) + | Type::Function(..) + | Type::Forall(_, _) + | Type::Constant(..) + | Type::Quoted(_) + | Type::InfixExpr(_, _, _) + | Type::Error => (), + } + + self.complete_type_methods( + typ, + prefix, + FunctionKind::SelfType(typ), + function_completion_kind, + self_prefix, + ); + } + + fn complete_type_methods( + &mut self, + typ: &Type, + prefix: &str, + function_kind: FunctionKind, + function_completion_kind: FunctionCompletionKind, + self_prefix: bool, + ) { + self.complete_trait_constraints_methods( + typ, + prefix, + function_kind, + function_completion_kind, + ); + + let Some(methods_by_name) = self.interner.get_type_methods(typ) else { + return; + }; + + let struct_id = get_type_struct_id(typ); + let is_primitive = typ.is_primitive(); + let has_self_param = matches!(function_kind, FunctionKind::SelfType(..)); + + for (name, methods) in methods_by_name { + if !name_matches(name, prefix) { + continue; + } + + for (func_id, trait_id) in + methods.find_matching_methods(typ, has_self_param, self.interner) + { + if let Some(struct_id) = struct_id { + let modifiers = self.interner.function_modifiers(&func_id); + let visibility = modifiers.visibility; + if !struct_member_is_visible( + struct_id, + visibility, + self.module_id, + self.def_maps, + ) { + continue; + } + } + + if let Some(trait_id) = trait_id { + let modifiers = self.interner.function_modifiers(&func_id); + let visibility = modifiers.visibility; + if !trait_member_is_visible(trait_id, visibility, self.module_id, self.def_maps) + { + continue; + } + } + + if is_primitive + && !method_call_is_visible( + typ, + func_id, + self.module_id, + self.interner, + self.def_maps, + ) + { + continue; + } + + let completion_items = self.function_completion_items( + name, + func_id, + function_completion_kind, + function_kind, + None, // attribute first type + trait_id, + self_prefix, + ); + if !completion_items.is_empty() { + self.completion_items.extend(completion_items); + self.suggested_module_def_ids.insert(ModuleDefId::FunctionId(func_id)); + } + } + } + } + + fn complete_trait_constraints_methods( + &mut self, + typ: &Type, + prefix: &str, + function_kind: FunctionKind, + function_completion_kind: FunctionCompletionKind, + ) { + let Some(func_id) = self.func_id else { + return; + }; + + let func_meta = self.interner.function_meta(&func_id); + for constraint in &func_meta.trait_constraints { + if *typ == constraint.typ { + let trait_ = self.interner.get_trait(constraint.trait_bound.trait_id); + self.complete_trait_methods( + trait_, + prefix, + function_kind, + function_completion_kind, + ); + } + } + } + + fn complete_trait_methods( + &mut self, + trait_: &Trait, + prefix: &str, + function_kind: FunctionKind, + function_completion_kind: FunctionCompletionKind, + ) { + let self_prefix = false; + + for (name, func_id) in &trait_.method_ids { + if name_matches(name, prefix) { + let completion_items = self.function_completion_items( + name, + *func_id, + function_completion_kind, + function_kind, + None, // attribute first type + None, // trait_id (we are suggesting methods for `Trait::>|<` so no need to auto-import it) + self_prefix, + ); + if !completion_items.is_empty() { + self.completion_items.extend(completion_items); + self.suggested_module_def_ids.insert(ModuleDefId::FunctionId(*func_id)); + } + } + } + } + + fn complete_struct_fields( + &mut self, + struct_type: &StructType, + generics: &[Type], + prefix: &str, + self_prefix: bool, + ) { + for (field_index, (name, visibility, typ)) in + struct_type.get_fields_with_visibility(generics).iter().enumerate() + { + if !struct_member_is_visible(struct_type.id, *visibility, self.module_id, self.def_maps) + { + continue; + } + + if !name_matches(name, prefix) { + continue; + } + + self.completion_items.push(self.struct_field_completion_item( + name, + typ, + struct_type.id, + field_index, + self_prefix, + )); + } + } + + fn complete_tuple_fields(&mut self, types: &[Type], self_prefix: bool) { + for (index, typ) in types.iter().enumerate() { + let name = index.to_string(); + self.completion_items.push(field_completion_item(&name, typ.to_string(), self_prefix)); + } + } + + #[allow(clippy::too_many_arguments)] + fn complete_in_module( + &mut self, + module_id: ModuleId, + prefix: &str, + path_kind: PathKind, + at_root: bool, + function_completion_kind: FunctionCompletionKind, + requested_items: RequestedItems, + ) { + let def_map = &self.def_maps[&module_id.krate]; + let Some(mut module_data) = def_map.modules().get(module_id.local_id.0) else { + return; + }; + + if at_root { + match path_kind { + PathKind::Crate => { + let Some(root_module_data) = def_map.modules().get(def_map.root().0) else { + return; + }; + module_data = root_module_data; + } + PathKind::Super => { + let Some(parent) = module_data.parent else { + return; + }; + let Some(parent_module_data) = def_map.modules().get(parent.0) else { + return; + }; + module_data = parent_module_data; + } + PathKind::Dep => (), + PathKind::Plain => (), + } + } + + let function_kind = FunctionKind::Any; + + for ident in module_data.scope().names() { + let name = &ident.0.contents; + + if name_matches(name, prefix) { + let per_ns = module_data.find_name(ident); + if let Some((module_def_id, visibility, _)) = per_ns.types { + if item_in_module_is_visible( + self.def_maps, + self.module_id, + module_id, + visibility, + ) { + let completion_items = self.module_def_id_completion_items( + module_def_id, + name.clone(), + function_completion_kind, + function_kind, + requested_items, + ); + if !completion_items.is_empty() { + self.completion_items.extend(completion_items); + self.suggested_module_def_ids.insert(module_def_id); + } + } + } + + if let Some((module_def_id, visibility, _)) = per_ns.values { + if item_in_module_is_visible( + self.def_maps, + self.module_id, + module_id, + visibility, + ) { + let completion_items = self.module_def_id_completion_items( + module_def_id, + name.clone(), + function_completion_kind, + function_kind, + requested_items, + ); + if !completion_items.is_empty() { + self.completion_items.extend(completion_items); + self.suggested_module_def_ids.insert(module_def_id); + } + } + } + } + } + + if at_root && path_kind == PathKind::Plain { + for dependency in self.dependencies { + let dependency_name = dependency.as_name(); + if name_matches(&dependency_name, prefix) { + let root_id = self.def_maps[&dependency.crate_id].root(); + let module_id = ModuleId { krate: dependency.crate_id, local_id: root_id }; + self.completion_items + .push(self.crate_completion_item(dependency_name, module_id)); + } + } + + if name_matches("crate::", prefix) { + self.completion_items.push(simple_completion_item( + "crate::", + CompletionItemKind::KEYWORD, + None, + )); + } + + if module_data.parent.is_some() && name_matches("super::", prefix) { + self.completion_items.push(simple_completion_item( + "super::", + CompletionItemKind::KEYWORD, + None, + )); + } + } + } + + fn resolve_module(&self, segments: Vec) -> Option { + if let Some(ModuleDefId::ModuleId(module_id)) = self.resolve_path(segments) { + Some(module_id) + } else { + None + } + } + + fn resolve_path(&self, segments: Vec) -> Option { + let last_segment = segments.last().unwrap().clone(); + + // If we can't resolve a path trough lookup, let's see if the last segment is bound to a type + let location = Location::new(last_segment.span(), self.file); + if let Some(reference_id) = self.interner.find_referenced(location) { + if let Some(id) = module_def_id_from_reference_id(reference_id) { + return Some(id); + } + } + + None + } + + fn suggest_no_arguments_attributes(&mut self, prefix: &str, attributes: &[&str]) { + for name in attributes { + if name_matches(name, prefix) { + self.completion_items.push(simple_completion_item( + *name, + CompletionItemKind::METHOD, + None, + )); + } + } + } + + fn suggest_one_argument_attributes(&mut self, prefix: &str, attributes: &[&str]) { + for name in attributes { + if name_matches(name, prefix) { + self.completion_items.push(snippet_completion_item( + format!("{}(…)", name), + CompletionItemKind::METHOD, + format!("{}(${{1:name}})", name), + None, + )); + } + } + } + + fn suggest_trait_impl_function( + &mut self, + noir_trait_impl: &NoirTraitImpl, + noir_function: &NoirFunction, + ) { + // First find the trait + let location = Location::new(noir_trait_impl.trait_name.span(), self.file); + let Some(ReferenceId::Trait(trait_id)) = self.interner.find_referenced(location) else { + return; + }; + + let trait_ = self.interner.get_trait(trait_id); + + // Get all methods + let mut method_ids = trait_.method_ids.clone(); + + // Remove the ones that already are implemented + for item in &noir_trait_impl.items { + if let TraitImplItemKind::Function(noir_function) = &item.item.kind { + method_ids.remove(noir_function.name()); + } + } + + let indent = 0; + + // Suggest the ones that match the name + let prefix = noir_function.name(); + for (name, func_id) in method_ids { + if !name_matches(&name, prefix) { + continue; + } + + let func_meta = self.interner.function_meta(&func_id); + let modifiers = self.interner.function_modifiers(&func_id); + + let mut generator = TraitImplMethodStubGenerator::new( + &name, + func_meta, + modifiers, + trait_, + noir_trait_impl, + self.interner, + self.def_maps, + self.module_id, + indent, + ); + generator.set_body("${1}".to_string()); + + let stub = generator.generate(); + + // We don't need the initial indent nor the final newlines + let stub = stub.trim(); + // We also don't need the leading "fn " as that's already in the code; + let stub = stub.strip_prefix("fn ").unwrap(); + + let label = if func_meta.parameters.is_empty() { + format!("fn {}()", &name) + } else { + format!("fn {}(..)", &name) + }; + + let completion_item = trait_impl_method_completion_item(label, stub); + let completion_item = self + .completion_item_with_doc_comments(ReferenceId::Function(func_id), completion_item); + + self.completion_items.push(completion_item); + } + } + + fn try_set_self_type(&mut self, pattern: &Pattern) { + match pattern { + Pattern::Identifier(ident) => { + if ident.0.contents == "self" { + let location = Location::new(ident.span(), self.file); + if let Some(ReferenceId::Local(definition_id)) = + self.interner.find_referenced(location) + { + self.self_type = + Some(self.interner.definition_type(definition_id).follow_bindings()); + } + } + } + Pattern::Mutable(pattern, ..) => self.try_set_self_type(pattern), + Pattern::Tuple(..) | Pattern::Struct(..) | Pattern::Interned(..) => (), + } + } + + fn get_lvalue_type(&self, lvalue: &LValue) -> Option { + match lvalue { + LValue::Ident(ident) => { + let location = Location::new(ident.span(), self.file); + if let Some(ReferenceId::Local(definition_id)) = + self.interner.find_referenced(location) + { + let typ = self.interner.definition_type(definition_id); + Some(typ) + } else { + None + } + } + LValue::MemberAccess { object, field_name, .. } => { + let typ = self.get_lvalue_type(object)?; + get_field_type(&typ, &field_name.0.contents) + } + LValue::Index { array, .. } => { + let typ = self.get_lvalue_type(array)?; + get_array_element_type(typ) + } + LValue::Dereference(lvalue, ..) => self.get_lvalue_type(lvalue), + LValue::Interned(..) => None, + } + } + + /// Determine where each segment in a `use` statement is located. + + fn includes_span(&self, span: Span) -> bool { + span.start() as usize <= self.byte_index && self.byte_index <= span.end() as usize + } +} + +impl<'a> Visitor for NodeFinder<'a> { + fn visit_item(&mut self, item: &Item) -> bool { + if let ItemKind::Import(use_tree, _) = &item.kind { + if let Some(lsp_location) = to_lsp_location(self.files, self.file, item.span) { + self.auto_import_line = (lsp_location.range.end.line + 1) as usize; + } + self.use_segment_positions.add(use_tree); + } + + self.includes_span(item.span) + } + + fn visit_import( + &mut self, + use_tree: &UseTree, + _span: Span, + _visibility: ItemVisibility, + ) -> bool { + let mut prefixes = Vec::new(); + self.find_in_use_tree(use_tree, &mut prefixes); + false + } + + fn visit_parsed_submodule(&mut self, parsed_sub_module: &ParsedSubModule, _span: Span) -> bool { + // Switch `self.module_id` to the submodule + let previous_module_id = self.module_id; + + let def_map = &self.def_maps[&self.module_id.krate]; + let Some(module_data) = def_map.modules().get(self.module_id.local_id.0) else { + return false; + }; + if let Some(child_module) = module_data.children.get(&parsed_sub_module.name) { + self.module_id = ModuleId { krate: self.module_id.krate, local_id: *child_module }; + } + + let old_auto_import_line = self.auto_import_line; + self.nesting += 1; + + if let Some(lsp_location) = + to_lsp_location(self.files, self.file, parsed_sub_module.name.span()) + { + self.auto_import_line = (lsp_location.range.start.line + 1) as usize; + } + + parsed_sub_module.accept_children(self); + + // Restore the old module before continuing + self.module_id = previous_module_id; + self.nesting -= 1; + self.auto_import_line = old_auto_import_line; + + false + } + + fn visit_noir_function(&mut self, noir_function: &NoirFunction, span: Span) -> bool { + for attribute in noir_function.secondary_attributes() { + attribute.accept(AttributeTarget::Function, self); + } + + let old_type_parameters = self.type_parameters.clone(); + self.collect_type_parameters_in_generics(&noir_function.def.generics); + + for param in &noir_function.def.parameters { + self.try_set_self_type(¶m.pattern); + param.typ.accept(self); + } + + noir_function.def.return_type.accept(self); + + for constraint in &noir_function.def.where_clause { + constraint.accept(self); + } + + self.local_variables.clear(); + for param in &noir_function.def.parameters { + self.collect_local_variables(¶m.pattern); + } + + let old_in_comptime = self.in_comptime; + self.in_comptime = noir_function.def.is_comptime; + + if let Some(ReferenceId::Function(func_id)) = self + .interner + .reference_at_location(Location::new(noir_function.name_ident().span(), self.file)) + { + self.func_id = Some(func_id); + } + + noir_function.def.body.accept(Some(span), self); + + self.func_id = None; + + self.in_comptime = old_in_comptime; + self.type_parameters = old_type_parameters; + self.self_type = None; + + false + } + + fn visit_noir_trait_impl(&mut self, noir_trait_impl: &NoirTraitImpl, _: Span) -> bool { + self.find_in_path(&noir_trait_impl.trait_name, RequestedItems::OnlyTypes); + noir_trait_impl.object_type.accept(self); + + self.type_parameters.clear(); + self.collect_type_parameters_in_generics(&noir_trait_impl.impl_generics); + + for item in &noir_trait_impl.items { + if let TraitImplItemKind::Function(noir_function) = &item.item.kind { + // Check if it's `fn foo>|<` and neither `(` nor `<` follow + if noir_function.name_ident().span().end() as usize == self.byte_index + && noir_function.parameters().is_empty() + { + let bytes = self.source.as_bytes(); + let mut cursor = self.byte_index; + while cursor < bytes.len() && bytes[cursor].is_ascii_whitespace() { + cursor += 1; + } + let char = bytes[cursor] as char; + if char != '(' && char != '<' { + self.suggest_trait_impl_function(noir_trait_impl, noir_function); + return false; + } + } + } + + item.item.accept(self); + } + + self.type_parameters.clear(); + + false + } + + fn visit_type_impl(&mut self, type_impl: &TypeImpl, _: Span) -> bool { + type_impl.object_type.accept(self); + + self.type_parameters.clear(); + self.collect_type_parameters_in_generics(&type_impl.generics); + + for (method, span) in &type_impl.methods { + method.item.accept(*span, self); + + // Optimization: stop looking in functions past the completion cursor + if span.end() as usize > self.byte_index { + break; + } + } + + self.type_parameters.clear(); + + false + } + + fn visit_noir_struct(&mut self, noir_struct: &NoirStruct, _: Span) -> bool { + for attribute in &noir_struct.attributes { + attribute.accept(AttributeTarget::Struct, self); + } + + self.type_parameters.clear(); + self.collect_type_parameters_in_generics(&noir_struct.generics); + + for field in &noir_struct.fields { + field.item.typ.accept(self); + } + + self.type_parameters.clear(); + + false + } + + fn visit_trait_item_function( + &mut self, + name: &Ident, + generics: &UnresolvedGenerics, + parameters: &[(Ident, UnresolvedType)], + return_type: &noirc_frontend::ast::FunctionReturnType, + where_clause: &[noirc_frontend::ast::UnresolvedTraitConstraint], + body: &Option, + ) -> bool { + let old_type_parameters = self.type_parameters.clone(); + self.collect_type_parameters_in_generics(generics); + + for (_name, unresolved_type) in parameters { + unresolved_type.accept(self); + } + + return_type.accept(self); + + for unresolved_trait_constraint in where_clause { + unresolved_trait_constraint.accept(self); + } + + if let Some(body) = body { + self.local_variables.clear(); + for (name, _) in parameters { + self.local_variables.insert(name.to_string(), name.span()); + } + + if let Some(ReferenceId::Function(func_id)) = + self.interner.reference_at_location(Location::new(name.span(), self.file)) + { + self.func_id = Some(func_id); + } + + body.accept(None, self); + + self.func_id = None; + }; + + self.type_parameters = old_type_parameters; + + false + } + + fn visit_call_expression(&mut self, call_expression: &CallExpression, _: Span) -> bool { + // + // foo::b>|<(...) + // + // In this case we want to suggest items in foo but if they are functions + // we don't want to insert arguments, because they are already there (even if + // they could be wrong) just because inserting them would lead to broken code. + if let ExpressionKind::Variable(path) = &call_expression.func.kind { + if self.includes_span(path.span) { + self.find_in_path_impl(path, RequestedItems::AnyItems, true); + return false; + } + } + + // Check if it's this case: + // + // foo.>|<(...) + // + // "foo." is actually broken, but it's parsed as "foo", so this is seen + // as "foo(...)" but if we are at a dot right after "foo" it means it's + // the above case and we want to suggest methods of foo's type. + let after_dot = self.byte == Some(b'.'); + if after_dot && call_expression.func.span.end() as usize == self.byte_index - 1 { + let location = Location::new(call_expression.func.span, self.file); + if let Some(typ) = self.interner.type_at_location(location) { + let prefix = ""; + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + prefix, + FunctionCompletionKind::Name, + self_prefix, + ); + return false; + } + } + + true + } + + fn visit_method_call_expression( + &mut self, + method_call_expression: &MethodCallExpression, + _: Span, + ) -> bool { + // Check if it's this case: + // + // foo.b>|<(...) + // + // In this case we want to suggest items in foo but if they are functions + // we don't want to insert arguments, because they are already there (even if + // they could be wrong) just because inserting them would lead to broken code. + if self.includes_span(method_call_expression.method_name.span()) { + let location = Location::new(method_call_expression.object.span, self.file); + if let Some(typ) = self.interner.type_at_location(location) { + let prefix = method_call_expression.method_name.to_string(); + let offset = + self.byte_index - method_call_expression.method_name.span().start() as usize; + let prefix = prefix[0..offset].to_string(); + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + &prefix, + FunctionCompletionKind::Name, + self_prefix, + ); + return false; + } + } + + true + } + + fn visit_block_expression( + &mut self, + block_expression: &BlockExpression, + _: Option, + ) -> bool { + let old_local_variables = self.local_variables.clone(); + for statement in &block_expression.statements { + statement.accept(self); + + // Optimization: stop looking in statements past the completion cursor + if statement.span.end() as usize > self.byte_index { + break; + } + } + self.local_variables = old_local_variables; + + false + } + + fn visit_let_statement(&mut self, let_statement: &LetStatement) -> bool { + let_statement.accept_children(self); + self.collect_local_variables(&let_statement.pattern); + false + } + + fn visit_global(&mut self, let_statement: &LetStatement, _: Span) -> bool { + let_statement.accept_children(self); + false + } + + fn visit_comptime_statement(&mut self, statement: &Statement) -> bool { + // When entering a comptime block, regular local variables shouldn't be offered anymore + let old_local_variables = self.local_variables.clone(); + self.local_variables.clear(); + + let old_in_comptime = self.in_comptime; + self.in_comptime = true; + + statement.accept(self); + + self.in_comptime = old_in_comptime; + self.local_variables = old_local_variables; + + false + } + + fn visit_for_loop_statement(&mut self, for_loop_statement: &ForLoopStatement) -> bool { + let old_local_variables = self.local_variables.clone(); + let ident = &for_loop_statement.identifier; + self.local_variables.insert(ident.to_string(), ident.span()); + + for_loop_statement.accept_children(self); + + self.local_variables = old_local_variables; + + false + } + + fn visit_lvalue_ident(&mut self, ident: &Ident) { + // If we have `foo.>|<` we suggest `foo`'s type fields and methods + if self.byte == Some(b'.') && ident.span().end() as usize == self.byte_index - 1 { + let location = Location::new(ident.span(), self.file); + if let Some(ReferenceId::Local(definition_id)) = self.interner.find_referenced(location) + { + let typ = self.interner.definition_type(definition_id); + let prefix = ""; + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + prefix, + FunctionCompletionKind::NameAndParameters, + self_prefix, + ); + } + } + } + + fn visit_lvalue_member_access( + &mut self, + object: &LValue, + field_name: &Ident, + span: Span, + ) -> bool { + // If we have `foo.bar.>|<` we solve the type of `foo`, get the field `bar`, + // then suggest methods of the resulting type. + if self.byte == Some(b'.') && span.end() as usize == self.byte_index - 1 { + if let Some(typ) = self.get_lvalue_type(object) { + if let Some(typ) = get_field_type(&typ, &field_name.0.contents) { + let prefix = ""; + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + prefix, + FunctionCompletionKind::NameAndParameters, + self_prefix, + ); + } + } + + return false; + } + true + } + + fn visit_lvalue_index(&mut self, array: &LValue, _index: &Expression, span: Span) -> bool { + // If we have `foo[index].>|<` we solve the type of `foo`, then get the array/slice element type, + // then suggest methods of that type. + if self.byte == Some(b'.') && span.end() as usize == self.byte_index - 1 { + if let Some(typ) = self.get_lvalue_type(array) { + if let Some(typ) = get_array_element_type(typ) { + let prefix = ""; + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + prefix, + FunctionCompletionKind::NameAndParameters, + self_prefix, + ); + } + } + return false; + } + true + } + + fn visit_lvalue_dereference(&mut self, lvalue: &LValue, span: Span) -> bool { + if self.byte == Some(b'.') && span.end() as usize == self.byte_index - 1 { + if let Some(typ) = self.get_lvalue_type(lvalue) { + let prefix = ""; + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + prefix, + FunctionCompletionKind::NameAndParameters, + self_prefix, + ); + } + return false; + } + + true + } + + fn visit_variable(&mut self, path: &Path, _: Span) -> bool { + self.find_in_path(path, RequestedItems::AnyItems); + false + } + + fn visit_expression(&mut self, expression: &Expression) -> bool { + expression.accept_children(self); + + // "foo." (no identifier afterwards) is parsed as the expression on the left hand-side of the dot. + // Here we check if there's a dot at the completion position, and if the expression + // ends right before the dot. If so, it means we want to complete the expression's type fields and methods. + // We only do this after visiting nested expressions, because in an expression like `foo & bar.` we want + // to complete for `bar`, not for `foo & bar`. + if self.completion_items.is_empty() + && self.byte == Some(b'.') + && expression.span.end() as usize == self.byte_index - 1 + { + let location = Location::new(expression.span, self.file); + if let Some(typ) = self.interner.type_at_location(location) { + let prefix = ""; + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + prefix, + FunctionCompletionKind::NameAndParameters, + self_prefix, + ); + } + } + + false + } + + fn visit_comptime_expression( + &mut self, + block_expression: &BlockExpression, + span: Span, + ) -> bool { + // When entering a comptime block, regular local variables shouldn't be offered anymore + let old_local_variables = self.local_variables.clone(); + self.local_variables.clear(); + + let old_in_comptime = self.in_comptime; + self.in_comptime = true; + + block_expression.accept(Some(span), self); + + self.in_comptime = old_in_comptime; + self.local_variables = old_local_variables; + + false + } + + fn visit_constructor_expression( + &mut self, + constructor_expression: &ConstructorExpression, + _: Span, + ) -> bool { + let UnresolvedTypeData::Named(path, _, _) = &constructor_expression.typ.typ else { + return true; + }; + + self.find_in_path(path, RequestedItems::OnlyTypes); + + // Check if we need to autocomplete the field name + if constructor_expression + .fields + .iter() + .any(|(field_name, _)| field_name.span().end() as usize == self.byte_index) + { + self.complete_constructor_field_name(constructor_expression); + return false; + } + + for (_field_name, expression) in &constructor_expression.fields { + expression.accept(self); + } + + false + } + + fn visit_member_access_expression( + &mut self, + member_access_expression: &MemberAccessExpression, + _: Span, + ) -> bool { + let ident = &member_access_expression.rhs; + + if self.byte_index == ident.span().end() as usize { + // Assuming member_access_expression is of the form `foo.bar`, we are right after `bar` + let location = Location::new(member_access_expression.lhs.span, self.file); + if let Some(typ) = self.interner.type_at_location(location) { + let prefix = ident.to_string().to_case(Case::Snake); + let self_prefix = false; + self.complete_type_fields_and_methods( + &typ, + &prefix, + FunctionCompletionKind::NameAndParameters, + self_prefix, + ); + return false; + } + } + + true + } + + fn visit_if_expression(&mut self, if_expression: &IfExpression, _: Span) -> bool { + if_expression.condition.accept(self); + + let old_local_variables = self.local_variables.clone(); + if_expression.consequence.accept(self); + self.local_variables = old_local_variables; + + if let Some(alternative) = &if_expression.alternative { + let old_local_variables = self.local_variables.clone(); + alternative.accept(self); + self.local_variables = old_local_variables; + } + + false + } + + fn visit_lambda(&mut self, lambda: &Lambda, _: Span) -> bool { + for (_, unresolved_type) in &lambda.parameters { + unresolved_type.accept(self); + } + + let old_local_variables = self.local_variables.clone(); + for (pattern, _) in &lambda.parameters { + self.collect_local_variables(pattern); + } + + lambda.body.accept(self); + + self.local_variables = old_local_variables; + + false + } + + fn visit_as_trait_path(&mut self, as_trait_path: &AsTraitPath, _: Span) -> bool { + self.find_in_path(&as_trait_path.trait_path, RequestedItems::OnlyTypes); + + false + } + + fn visit_unresolved_type(&mut self, unresolved_type: &UnresolvedType) -> bool { + self.includes_span(unresolved_type.span) + } + + fn visit_named_type( + &mut self, + path: &Path, + unresolved_types: &GenericTypeArgs, + _: Span, + ) -> bool { + self.find_in_path(path, RequestedItems::OnlyTypes); + unresolved_types.accept(self); + false + } + + fn visit_type_path(&mut self, type_path: &TypePath, _: Span) -> bool { + if type_path.item.span().end() as usize != self.byte_index { + return true; + } + + let typ = match &type_path.typ.typ { + UnresolvedTypeData::FieldElement => Some(Type::FieldElement), + UnresolvedTypeData::Integer(signedness, integer_bit_size) => { + Some(Type::Integer(*signedness, *integer_bit_size)) + } + UnresolvedTypeData::Bool => Some(Type::Bool), + UnresolvedTypeData::String(UnresolvedTypeExpression::Constant(value, _)) => { + Some(Type::String(Box::new(Type::Constant( + *value, + Kind::Numeric(Box::new(Type::Integer( + Signedness::Unsigned, + IntegerBitSize::ThirtyTwo, + ))), + )))) + } + UnresolvedTypeData::Quoted(quoted_type) => Some(Type::Quoted(*quoted_type)), + _ => None, + }; + + if let Some(typ) = typ { + let prefix = &type_path.item.0.contents; + self.complete_type_methods( + &typ, + prefix, + FunctionKind::Any, + FunctionCompletionKind::NameAndParameters, + false, // self_prefix + ); + } + + false + } + + fn visit_meta_attribute(&mut self, attribute: &MetaAttribute, target: AttributeTarget) -> bool { + if self.byte_index == attribute.name.span.end() as usize { + self.suggest_builtin_attributes(&attribute.name.to_string(), target); + } + + self.find_in_path(&attribute.name, RequestedItems::OnlyAttributeFunctions(target)); + + true + } + + fn visit_quote(&mut self, tokens: &Tokens) { + let mut last_was_dollar = false; + + for token in &tokens.0 { + let span = token.to_span(); + if span.end() as usize > self.byte_index { + break; + } + + let token = token.token(); + + if let Token::DollarSign = token { + if span.end() as usize == self.byte_index { + self.local_variables_completion(""); + break; + } + + last_was_dollar = true; + continue; + } + + if span.end() as usize == self.byte_index { + let prefix = token.to_string(); + if last_was_dollar { + self.local_variables_completion(&prefix); + } + break; + } + + last_was_dollar = false; + } + } + + fn visit_trait_bound(&mut self, trait_bound: &TraitBound) -> bool { + self.find_in_path(&trait_bound.trait_path, RequestedItems::OnlyTraits); + trait_bound.trait_generics.accept(self); + false + } +} + +fn get_field_type(typ: &Type, name: &str) -> Option { + match typ { + Type::Struct(struct_type, generics) => { + Some(struct_type.borrow().get_field(name, generics)?.0) + } + Type::Tuple(types) => { + if let Ok(index) = name.parse::() { + types.get(index as usize).cloned() + } else { + None + } + } + Type::Alias(alias_type, generics) => Some(alias_type.borrow().get_type(generics)), + Type::TypeVariable(var) | Type::NamedGeneric(var, _) => { + if let TypeBinding::Bound(ref typ) = &*var.borrow() { + get_field_type(typ, name) + } else { + None + } + } + _ => None, + } +} + +fn get_array_element_type(typ: Type) -> Option { + match typ { + Type::Array(_, typ) | Type::Slice(typ) => Some(*typ), + Type::Alias(alias_type, generics) => { + let typ = alias_type.borrow().get_type(&generics); + get_array_element_type(typ) + } + Type::TypeVariable(var) | Type::NamedGeneric(var, _) => { + if let TypeBinding::Bound(typ) = &*var.borrow() { + get_array_element_type(typ.clone()) + } else { + None + } + } + _ => None, + } +} + +fn get_type_struct_id(typ: &Type) -> Option { + match typ { + Type::Struct(struct_type, _) => Some(struct_type.borrow().id), + Type::Alias(type_alias, generics) => { + let type_alias = type_alias.borrow(); + let typ = type_alias.get_type(generics); + get_type_struct_id(&typ) + } + _ => None, + } +} + +/// Returns true if name matches a prefix written in code. +/// `prefix` must already be in snake case. +/// This method splits both name and prefix by underscore, +/// then checks that every part of name starts with a part of +/// prefix, in order. +/// +/// For example: +/// +/// // "merk" and "ro" match "merkle" and "root" and are in order +/// name_matches("compute_merkle_root", "merk_ro") == true +/// +/// // "ro" matches "root", but "merkle" comes before it, so no match +/// name_matches("compute_merkle_root", "ro_mer") == false +/// +/// // neither "compute" nor "merkle" nor "root" start with "oot" +/// name_matches("compute_merkle_root", "oot") == false +fn name_matches(name: &str, prefix: &str) -> bool { + let name = name.to_case(Case::Snake); + let name_parts: Vec<&str> = name.split('_').collect(); + + let mut last_index: i32 = -1; + for prefix_part in prefix.split('_') { + // Look past parts we already matched + let offset = if last_index >= 0 { last_index as usize + 1 } else { 0 }; + + if let Some(mut name_part_index) = + name_parts.iter().skip(offset).position(|name_part| name_part.starts_with(prefix_part)) + { + // Need to adjust the index if we skipped some segments + name_part_index += offset; + + if last_index >= name_part_index as i32 { + return false; + } + last_index = name_part_index as i32; + } else { + return false; + } + } + + true +} + +fn module_def_id_from_reference_id(reference_id: ReferenceId) -> Option { + match reference_id { + ReferenceId::Module(module_id) => Some(ModuleDefId::ModuleId(module_id)), + ReferenceId::Struct(struct_id) => Some(ModuleDefId::TypeId(struct_id)), + ReferenceId::Trait(trait_id) => Some(ModuleDefId::TraitId(trait_id)), + ReferenceId::Function(func_id) => Some(ModuleDefId::FunctionId(func_id)), + ReferenceId::Alias(type_alias_id) => Some(ModuleDefId::TypeAliasId(type_alias_id)), + ReferenceId::StructMember(_, _) + | ReferenceId::Global(_) + | ReferenceId::Local(_) + | ReferenceId::Reference(_, _) => None, + } +} + +#[cfg(test)] +mod completion_name_matches_tests { + use crate::requests::completion::name_matches; + + #[test] + fn test_name_matches() { + assert!(name_matches("foo", "foo")); + assert!(name_matches("foo_bar", "bar")); + assert!(name_matches("FooBar", "foo")); + assert!(name_matches("FooBar", "bar")); + assert!(name_matches("FooBar", "foo_bar")); + assert!(name_matches("bar_baz", "bar_b")); + + assert!(!name_matches("foo_bar", "o_b")); + } +} diff --git a/tooling/lsp/src/requests/completion/auto_import.rs b/tooling/lsp/src/requests/completion/auto_import.rs new file mode 100644 index 00000000000..0e80b284f32 --- /dev/null +++ b/tooling/lsp/src/requests/completion/auto_import.rs @@ -0,0 +1,112 @@ +use noirc_frontend::hir::def_map::ModuleDefId; + +use crate::{ + modules::{relative_module_full_path, relative_module_id_path}, + use_segment_positions::{ + use_completion_item_additional_text_edits, UseCompletionItemAdditionTextEditsRequest, + }, + visibility::module_def_id_is_visible, +}; + +use super::{ + kinds::{FunctionCompletionKind, FunctionKind, RequestedItems}, + name_matches, + sort_text::auto_import_sort_text, + NodeFinder, +}; + +impl<'a> NodeFinder<'a> { + pub(super) fn complete_auto_imports( + &mut self, + prefix: &str, + requested_items: RequestedItems, + function_completion_kind: FunctionCompletionKind, + ) { + let current_module_parent_id = self.module_id.parent(self.def_maps); + + for (name, entries) in self.interner.get_auto_import_names() { + if !name_matches(name, prefix) { + continue; + } + + for (module_def_id, visibility, defining_module) in entries { + if self.suggested_module_def_ids.contains(module_def_id) { + continue; + } + + if !module_def_id_is_visible( + *module_def_id, + self.module_id, + *visibility, + *defining_module, + self.interner, + self.def_maps, + ) { + continue; + } + + let completion_items = self.module_def_id_completion_items( + *module_def_id, + name.clone(), + function_completion_kind, + FunctionKind::Any, + requested_items, + ); + + if completion_items.is_empty() { + continue; + }; + + self.suggested_module_def_ids.insert(*module_def_id); + + for mut completion_item in completion_items { + let module_full_path = if let Some(defining_module) = defining_module { + relative_module_id_path( + *defining_module, + &self.module_id, + current_module_parent_id, + self.interner, + ) + } else { + let Some(module_full_path) = relative_module_full_path( + *module_def_id, + self.module_id, + current_module_parent_id, + self.interner, + ) else { + continue; + }; + module_full_path + }; + + let full_path = if defining_module.is_some() + || !matches!(module_def_id, ModuleDefId::ModuleId(..)) + { + format!("{}::{}", module_full_path, name) + } else { + module_full_path + }; + + let mut label_details = completion_item.label_details.unwrap(); + label_details.detail = Some(format!("(use {})", full_path)); + completion_item.label_details = Some(label_details); + completion_item.additional_text_edits = + Some(use_completion_item_additional_text_edits( + UseCompletionItemAdditionTextEditsRequest { + full_path: &full_path, + files: self.files, + file: self.file, + lines: &self.lines, + nesting: self.nesting, + auto_import_line: self.auto_import_line, + }, + &self.use_segment_positions, + )); + completion_item.sort_text = Some(auto_import_sort_text()); + + self.completion_items.push(completion_item); + } + } + } + } +} diff --git a/tooling/lsp/src/requests/completion/builtins.rs b/tooling/lsp/src/requests/completion/builtins.rs new file mode 100644 index 00000000000..c0910e9005e --- /dev/null +++ b/tooling/lsp/src/requests/completion/builtins.rs @@ -0,0 +1,288 @@ +use lsp_types::CompletionItemKind; +use noirc_frontend::{ast::AttributeTarget, token::Keyword}; +use strum::IntoEnumIterator; + +use super::{ + completion_items::{ + completion_item_with_trigger_parameter_hints_command, simple_completion_item, + snippet_completion_item, + }, + kinds::FunctionCompletionKind, + name_matches, NodeFinder, +}; + +impl<'a> NodeFinder<'a> { + pub(super) fn builtin_functions_completion( + &mut self, + prefix: &str, + function_completion_kind: FunctionCompletionKind, + ) { + for keyword in Keyword::iter() { + if let Some(func) = keyword_builtin_function(&keyword) { + if name_matches(func.name, prefix) { + let description = Some(func.description.to_string()); + let label; + let insert_text; + match function_completion_kind { + FunctionCompletionKind::Name => { + label = func.name.to_string(); + insert_text = func.name.to_string(); + } + FunctionCompletionKind::NameAndParameters => { + label = format!("{}(…)", func.name); + insert_text = format!("{}({})", func.name, func.parameters); + } + } + + self.completion_items.push( + completion_item_with_trigger_parameter_hints_command( + snippet_completion_item( + label, + CompletionItemKind::FUNCTION, + insert_text, + description, + ), + ), + ); + } + } + } + } + + pub(super) fn builtin_values_completion(&mut self, prefix: &str) { + for keyword in ["false", "true"] { + if name_matches(keyword, prefix) { + self.completion_items.push(simple_completion_item( + keyword, + CompletionItemKind::KEYWORD, + Some("bool".to_string()), + )); + } + } + } + + pub(super) fn builtin_types_completion(&mut self, prefix: &str) { + for keyword in Keyword::iter() { + if let Some(typ) = keyword_builtin_type(&keyword) { + if name_matches(typ, prefix) { + self.completion_items.push(simple_completion_item( + typ, + CompletionItemKind::STRUCT, + Some(typ.to_string()), + )); + } + } + } + + for typ in builtin_integer_types() { + if name_matches(typ, prefix) { + self.completion_items.push(simple_completion_item( + typ, + CompletionItemKind::STRUCT, + Some(typ.to_string()), + )); + } + } + } + + pub(super) fn suggest_builtin_attributes(&mut self, prefix: &str, target: AttributeTarget) { + match target { + AttributeTarget::Module | AttributeTarget::Trait => (), + AttributeTarget::Struct => { + self.suggest_one_argument_attributes(prefix, &["abi"]); + } + AttributeTarget::Function => { + let no_arguments_attributes = &[ + "contract_library_method", + "deprecated", + "export", + "fold", + "no_predicates", + "recursive", + "test", + "varargs", + ]; + self.suggest_no_arguments_attributes(prefix, no_arguments_attributes); + + let one_argument_attributes = &["abi", "field", "foreign", "oracle"]; + self.suggest_one_argument_attributes(prefix, one_argument_attributes); + + if name_matches("deprecated", prefix) { + self.completion_items.push(snippet_completion_item( + "deprecated(\"...\")", + CompletionItemKind::METHOD, + "deprecated(\"${1:message}\")", + None, + )); + } + + if name_matches("test", prefix) || name_matches("should_fail", prefix) { + self.completion_items.push(snippet_completion_item( + "test(should_fail)", + CompletionItemKind::METHOD, + "test(should_fail)", + None, + )); + } + + if name_matches("test", prefix) || name_matches("should_fail_with", prefix) { + self.completion_items.push(snippet_completion_item( + "test(should_fail_with = \"...\")", + CompletionItemKind::METHOD, + "test(should_fail_with = \"${1:message}\")", + None, + )); + } + } + AttributeTarget::Let => { + if name_matches("allow", prefix) || name_matches("unused_variables", prefix) { + self.completion_items.push(simple_completion_item( + "allow(unused_variables)", + CompletionItemKind::METHOD, + None, + )); + } + } + } + } +} + +pub(super) fn builtin_integer_types() -> [&'static str; 8] { + ["i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64"] +} + +/// If a keyword corresponds to a built-in type, returns that type's name. +pub(super) fn keyword_builtin_type(keyword: &Keyword) -> Option<&'static str> { + match keyword { + Keyword::Bool => Some("bool"), + Keyword::CtString => Some("CtString"), + Keyword::Expr => Some("Expr"), + Keyword::Field => Some("Field"), + Keyword::FunctionDefinition => Some("FunctionDefinition"), + Keyword::Module => Some("Module"), + Keyword::Quoted => Some("Quoted"), + Keyword::StructDefinition => Some("StructDefinition"), + Keyword::TraitConstraint => Some("TraitConstraint"), + Keyword::TraitDefinition => Some("TraitDefinition"), + Keyword::TraitImpl => Some("TraitImpl"), + Keyword::TypedExpr => Some("TypedExpr"), + Keyword::TypeType => Some("Type"), + Keyword::UnresolvedType => Some("UnresolvedType"), + + Keyword::As + | Keyword::Assert + | Keyword::AssertEq + | Keyword::Break + | Keyword::CallData + | Keyword::Char + | Keyword::Comptime + | Keyword::Constrain + | Keyword::Continue + | Keyword::Contract + | Keyword::Crate + | Keyword::Dep + | Keyword::Else + | Keyword::Enum + | Keyword::Fn + | Keyword::For + | Keyword::FormatString + | Keyword::Global + | Keyword::If + | Keyword::Impl + | Keyword::In + | Keyword::Let + | Keyword::Match + | Keyword::Mod + | Keyword::Mut + | Keyword::Pub + | Keyword::Return + | Keyword::ReturnData + | Keyword::String + | Keyword::Struct + | Keyword::Super + | Keyword::TopLevelItem + | Keyword::Trait + | Keyword::Type + | Keyword::Unchecked + | Keyword::Unconstrained + | Keyword::Unsafe + | Keyword::Use + | Keyword::Where + | Keyword::While => None, + } +} + +pub(super) struct BuiltInFunction { + pub(super) name: &'static str, + pub(super) parameters: &'static str, + pub(super) description: &'static str, +} + +/// If a keyword corresponds to a built-in function, returns info about it +pub(super) fn keyword_builtin_function(keyword: &Keyword) -> Option { + match keyword { + Keyword::Assert => Some(BuiltInFunction { + name: "assert", + parameters: "${1:predicate}", + description: "fn(T)", + }), + Keyword::AssertEq => Some(BuiltInFunction { + name: "assert_eq", + parameters: "${1:lhs}, ${2:rhs}", + description: "fn(T, T)", + }), + + Keyword::As + | Keyword::Bool + | Keyword::Break + | Keyword::CallData + | Keyword::Char + | Keyword::Comptime + | Keyword::Constrain + | Keyword::Continue + | Keyword::Contract + | Keyword::Crate + | Keyword::CtString + | Keyword::Dep + | Keyword::Else + | Keyword::Enum + | Keyword::Expr + | Keyword::Field + | Keyword::Fn + | Keyword::For + | Keyword::FormatString + | Keyword::FunctionDefinition + | Keyword::Global + | Keyword::If + | Keyword::Impl + | Keyword::In + | Keyword::Let + | Keyword::Match + | Keyword::Mod + | Keyword::Module + | Keyword::Mut + | Keyword::Pub + | Keyword::Quoted + | Keyword::Return + | Keyword::ReturnData + | Keyword::String + | Keyword::Struct + | Keyword::StructDefinition + | Keyword::Super + | Keyword::TopLevelItem + | Keyword::Trait + | Keyword::TraitConstraint + | Keyword::TraitDefinition + | Keyword::TraitImpl + | Keyword::Type + | Keyword::TypedExpr + | Keyword::TypeType + | Keyword::Unchecked + | Keyword::Unconstrained + | Keyword::UnresolvedType + | Keyword::Unsafe + | Keyword::Use + | Keyword::Where + | Keyword::While => None, + } +} diff --git a/tooling/lsp/src/requests/completion/completion_items.rs b/tooling/lsp/src/requests/completion/completion_items.rs new file mode 100644 index 00000000000..86bb308ee39 --- /dev/null +++ b/tooling/lsp/src/requests/completion/completion_items.rs @@ -0,0 +1,641 @@ +use lsp_types::{ + Command, CompletionItem, CompletionItemKind, CompletionItemLabelDetails, Documentation, + InsertTextFormat, MarkupContent, MarkupKind, +}; +use noirc_frontend::{ + ast::AttributeTarget, + hir::def_map::{ModuleDefId, ModuleId}, + hir_def::{function::FuncMeta, stmt::HirPattern}, + node_interner::{FuncId, GlobalId, ReferenceId, StructId, TraitId, TypeAliasId}, + QuotedType, Type, +}; + +use crate::{ + modules::relative_module_full_path, + use_segment_positions::{ + use_completion_item_additional_text_edits, UseCompletionItemAdditionTextEditsRequest, + }, +}; + +use super::{ + sort_text::{ + crate_or_module_sort_text, default_sort_text, new_sort_text, operator_sort_text, + self_mismatch_sort_text, + }, + FunctionCompletionKind, FunctionKind, NodeFinder, RequestedItems, +}; + +impl<'a> NodeFinder<'a> { + pub(super) fn module_def_id_completion_items( + &self, + module_def_id: ModuleDefId, + name: String, + function_completion_kind: FunctionCompletionKind, + function_kind: FunctionKind, + requested_items: RequestedItems, + ) -> Vec { + match requested_items { + RequestedItems::OnlyTypes => match module_def_id { + ModuleDefId::FunctionId(_) | ModuleDefId::GlobalId(_) => return Vec::new(), + ModuleDefId::ModuleId(_) + | ModuleDefId::TypeId(_) + | ModuleDefId::TypeAliasId(_) + | ModuleDefId::TraitId(_) => (), + }, + RequestedItems::OnlyTraits => match module_def_id { + ModuleDefId::FunctionId(_) | ModuleDefId::GlobalId(_) | ModuleDefId::TypeId(_) => { + return Vec::new() + } + ModuleDefId::ModuleId(_) + | ModuleDefId::TypeAliasId(_) + | ModuleDefId::TraitId(_) => (), + }, + RequestedItems::OnlyAttributeFunctions(..) => { + if !matches!(module_def_id, ModuleDefId::FunctionId(..)) { + return Vec::new(); + } + } + RequestedItems::AnyItems => (), + } + + let attribute_first_type = + if let RequestedItems::OnlyAttributeFunctions(target) = requested_items { + match target { + AttributeTarget::Module => Some(Type::Quoted(QuotedType::Module)), + AttributeTarget::Struct => Some(Type::Quoted(QuotedType::StructDefinition)), + AttributeTarget::Trait => Some(Type::Quoted(QuotedType::TraitDefinition)), + AttributeTarget::Function => Some(Type::Quoted(QuotedType::FunctionDefinition)), + AttributeTarget::Let => { + // No item can be suggested for a let statement attribute + return Vec::new(); + } + } + } else { + None + }; + + match module_def_id { + ModuleDefId::ModuleId(id) => vec![self.module_completion_item(name, id)], + ModuleDefId::FunctionId(func_id) => self.function_completion_items( + &name, + func_id, + function_completion_kind, + function_kind, + attribute_first_type.as_ref(), + None, // trait_id + false, // self_prefix + ), + ModuleDefId::TypeId(struct_id) => vec![self.struct_completion_item(name, struct_id)], + ModuleDefId::TypeAliasId(id) => vec![self.type_alias_completion_item(name, id)], + ModuleDefId::TraitId(trait_id) => vec![self.trait_completion_item(name, trait_id)], + ModuleDefId::GlobalId(global_id) => vec![self.global_completion_item(name, global_id)], + } + } + + pub(super) fn crate_completion_item( + &self, + name: impl Into, + id: ModuleId, + ) -> CompletionItem { + self.module_completion_item(name, id) + } + + pub(super) fn module_completion_item( + &self, + name: impl Into, + id: ModuleId, + ) -> CompletionItem { + let completion_item = module_completion_item(name); + self.completion_item_with_doc_comments(ReferenceId::Module(id), completion_item) + } + + fn struct_completion_item(&self, name: String, struct_id: StructId) -> CompletionItem { + let completion_item = + simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)); + self.completion_item_with_doc_comments(ReferenceId::Struct(struct_id), completion_item) + } + + pub(super) fn struct_field_completion_item( + &self, + field: &str, + typ: &Type, + struct_id: StructId, + field_index: usize, + self_type: bool, + ) -> CompletionItem { + let completion_item = struct_field_completion_item(field, typ, self_type); + self.completion_item_with_doc_comments( + ReferenceId::StructMember(struct_id, field_index), + completion_item, + ) + } + + fn type_alias_completion_item(&self, name: String, id: TypeAliasId) -> CompletionItem { + let completion_item = + simple_completion_item(name.clone(), CompletionItemKind::STRUCT, Some(name)); + self.completion_item_with_doc_comments(ReferenceId::Alias(id), completion_item) + } + + fn trait_completion_item(&self, name: String, trait_id: TraitId) -> CompletionItem { + let completion_item = + simple_completion_item(name.clone(), CompletionItemKind::INTERFACE, Some(name)); + self.completion_item_with_doc_comments(ReferenceId::Trait(trait_id), completion_item) + } + + fn global_completion_item(&self, name: String, global_id: GlobalId) -> CompletionItem { + let global = self.interner.get_global(global_id); + let typ = self.interner.definition_type(global.definition_id); + let description = typ.to_string(); + + let completion_item = + simple_completion_item(name, CompletionItemKind::CONSTANT, Some(description)); + self.completion_item_with_doc_comments(ReferenceId::Global(global_id), completion_item) + } + + #[allow(clippy::too_many_arguments)] + pub(super) fn function_completion_items( + &self, + name: &String, + func_id: FuncId, + function_completion_kind: FunctionCompletionKind, + function_kind: FunctionKind, + attribute_first_type: Option<&Type>, + trait_id: Option, + self_prefix: bool, + ) -> Vec { + let func_meta = self.interner.function_meta(&func_id); + + let func_self_type = if let Some((pattern, typ, _)) = func_meta.parameters.0.first() { + if self.hir_pattern_is_self_type(pattern) { + if let Type::MutableReference(mut_typ) = typ { + let typ: &Type = mut_typ; + Some(typ) + } else { + Some(typ) + } + } else { + None + } + } else { + None + }; + + if let Some(attribute_first_type) = attribute_first_type { + if func_meta.parameters.is_empty() { + return Vec::new(); + } + + let (_, typ, _) = &func_meta.parameters.0[0]; + if typ != attribute_first_type { + return Vec::new(); + } + } + + match function_kind { + FunctionKind::Any => (), + FunctionKind::SelfType(mut self_type) => { + if let Some(func_self_type) = func_self_type { + if matches!(self_type, Type::Integer(..)) + || matches!(self_type, Type::FieldElement) + { + // Check that the pattern type is the same as self type. + // We do this because some types (only Field and integer types) + // have their methods in the same HashMap. + + if let Type::MutableReference(mut_typ) = self_type { + self_type = mut_typ; + } + + if self_type != func_self_type { + return Vec::new(); + } + } else if let Type::Tuple(self_tuple_types) = self_type { + // Tuple types of different lengths seem to also have methods defined on all of them, + // so here we reject methods for tuples where the length doesn't match. + if let Type::Tuple(func_self_tuple_types) = func_self_type { + if self_tuple_types.len() != func_self_tuple_types.len() { + return Vec::new(); + } + } + } + } else { + return Vec::new(); + } + } + } + + let make_completion_item = |is_macro_call| { + self.function_completion_item( + name, + func_id, + func_meta, + func_self_type, + function_completion_kind, + function_kind, + attribute_first_type, + trait_id, + self_prefix, + is_macro_call, + ) + }; + + // When suggesting functions in attributes, never suggest a macro call + if attribute_first_type.is_some() { + return vec![make_completion_item(false)]; + } + + // Special case: the `unquote` macro + // (it's unlikely users will define a function named `unquote` that does something different than std's unquote) + if name == "unquote" { + return vec![make_completion_item(true)]; + } + + let modifiers = self.interner.function_modifiers(&func_id); + if modifiers.is_comptime + && matches!(func_meta.return_type(), Type::Quoted(QuotedType::Quoted)) + { + if self.in_comptime { + vec![make_completion_item(false), make_completion_item(true)] + } else { + // If not in a comptime block we can't operate with comptime values so the only thing + // we can do is call a macro. + vec![make_completion_item(true)] + } + } else { + vec![make_completion_item(false)] + } + } + + #[allow(clippy::too_many_arguments)] + pub(super) fn function_completion_item( + &self, + name: &String, + func_id: FuncId, + func_meta: &FuncMeta, + func_self_type: Option<&Type>, + function_completion_kind: FunctionCompletionKind, + function_kind: FunctionKind, + attribute_first_type: Option<&Type>, + trait_id: Option, + self_prefix: bool, + is_macro_call: bool, + ) -> CompletionItem { + let is_operator = if let Some(trait_impl_id) = &func_meta.trait_impl { + let trait_impl = self.interner.get_trait_implementation(*trait_impl_id); + let trait_impl = trait_impl.borrow(); + self.interner.is_operator_trait(trait_impl.trait_id) + } else { + false + }; + let name = if self_prefix { format!("self.{}", name) } else { name.clone() }; + let name = if is_macro_call { format!("{}!", name) } else { name }; + let name = &name; + let description = func_meta_type_to_string(func_meta, func_self_type.is_some()); + let mut has_arguments = false; + + let completion_item = match function_completion_kind { + FunctionCompletionKind::Name => simple_completion_item( + name, + CompletionItemKind::FUNCTION, + Some(description.clone()), + ), + FunctionCompletionKind::NameAndParameters => { + let kind = CompletionItemKind::FUNCTION; + let skip_first_argument = attribute_first_type.is_some(); + let insert_text = self.compute_function_insert_text( + func_meta, + name, + function_kind, + skip_first_argument, + ); + + if insert_text.ends_with("()") { + let label = + if skip_first_argument { name.to_string() } else { format!("{}()", name) }; + simple_completion_item(label, kind, Some(description.clone())) + } else { + has_arguments = true; + snippet_completion_item( + format!("{}(…)", name), + kind, + insert_text, + Some(description.clone()), + ) + } + } + }; + + let completion_item = completion_item_with_detail(completion_item, description); + + let completion_item = if is_operator { + completion_item_with_sort_text(completion_item, operator_sort_text()) + } else if function_kind == FunctionKind::Any && name == "new" { + completion_item_with_sort_text(completion_item, new_sort_text()) + } else if function_kind == FunctionKind::Any && func_self_type.is_some() { + completion_item_with_sort_text(completion_item, self_mismatch_sort_text()) + } else { + completion_item + }; + + let mut completion_item = match function_completion_kind { + FunctionCompletionKind::Name => completion_item, + FunctionCompletionKind::NameAndParameters => { + if has_arguments { + completion_item_with_trigger_parameter_hints_command(completion_item) + } else { + completion_item + } + } + }; + + self.auto_import_trait_if_trait_method(func_id, trait_id, &mut completion_item); + + self.completion_item_with_doc_comments(ReferenceId::Function(func_id), completion_item) + } + + fn auto_import_trait_if_trait_method( + &self, + func_id: FuncId, + trait_id: Option, + completion_item: &mut CompletionItem, + ) -> Option<()> { + // If this is a trait method, check if the trait is in scope + let trait_ = self.interner.get_trait(trait_id?); + let module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + if !module_data.scope().find_name(&trait_.name).is_none() { + return None; + } + // If not, automatically import it + let current_module_parent_id = self.module_id.parent(self.def_maps); + let module_full_path = relative_module_full_path( + ModuleDefId::FunctionId(func_id), + self.module_id, + current_module_parent_id, + self.interner, + )?; + let full_path = format!("{}::{}", module_full_path, trait_.name); + let mut label_details = completion_item.label_details.clone().unwrap(); + label_details.detail = Some(format!("(use {})", full_path)); + completion_item.label_details = Some(label_details); + completion_item.additional_text_edits = Some(use_completion_item_additional_text_edits( + UseCompletionItemAdditionTextEditsRequest { + full_path: &full_path, + files: self.files, + file: self.file, + lines: &self.lines, + nesting: self.nesting, + auto_import_line: self.auto_import_line, + }, + &self.use_segment_positions, + )); + + None + } + + fn compute_function_insert_text( + &self, + func_meta: &FuncMeta, + name: &str, + function_kind: FunctionKind, + skip_first_argument: bool, + ) -> String { + let mut text = String::new(); + text.push_str(name); + text.push('('); + + let mut parameters = func_meta.parameters.0.iter(); + if skip_first_argument { + parameters.next(); + } + + let mut index = 1; + for (pattern, _, _) in parameters { + if index == 1 { + match function_kind { + FunctionKind::SelfType(_) => { + if self.hir_pattern_is_self_type(pattern) { + continue; + } + } + FunctionKind::Any => (), + } + } + + if index > 1 { + text.push_str(", "); + } + + text.push_str("${"); + text.push_str(&index.to_string()); + text.push(':'); + self.hir_pattern_to_argument(pattern, &mut text); + text.push('}'); + + index += 1; + } + text.push(')'); + text + } + + pub(super) fn completion_item_with_doc_comments( + &self, + id: ReferenceId, + completion_item: CompletionItem, + ) -> CompletionItem { + if let Some(doc_comments) = self.interner.doc_comments(id) { + let docs = doc_comments.join("\n"); + CompletionItem { + documentation: Some(Documentation::MarkupContent(MarkupContent { + kind: MarkupKind::Markdown, + value: docs, + })), + ..completion_item + } + } else { + completion_item + } + } + + fn hir_pattern_to_argument(&self, pattern: &HirPattern, text: &mut String) { + match pattern { + HirPattern::Identifier(hir_ident) => { + text.push_str(self.interner.definition_name(hir_ident.id)); + } + HirPattern::Mutable(pattern, _) => self.hir_pattern_to_argument(pattern, text), + HirPattern::Tuple(_, _) | HirPattern::Struct(_, _, _) => text.push('_'), + } + } + + fn hir_pattern_is_self_type(&self, pattern: &HirPattern) -> bool { + match pattern { + HirPattern::Identifier(hir_ident) => { + let name = self.interner.definition_name(hir_ident.id); + name == "self" || name == "_self" + } + HirPattern::Mutable(pattern, _) => self.hir_pattern_is_self_type(pattern), + HirPattern::Tuple(_, _) | HirPattern::Struct(_, _, _) => false, + } + } +} + +pub(super) fn module_completion_item(name: impl Into) -> CompletionItem { + completion_item_with_sort_text( + simple_completion_item(name, CompletionItemKind::MODULE, None), + crate_or_module_sort_text(), + ) +} + +pub(super) fn trait_impl_method_completion_item( + label: impl Into, + insert_text: impl Into, +) -> CompletionItem { + snippet_completion_item(label, CompletionItemKind::METHOD, insert_text, None) +} + +fn func_meta_type_to_string(func_meta: &FuncMeta, has_self_type: bool) -> String { + let mut typ = &func_meta.typ; + if let Type::Forall(_, typ_) = typ { + typ = typ_; + } + + if let Type::Function(args, ret, _env, unconstrained) = typ { + let mut string = String::new(); + if *unconstrained { + string.push_str("unconstrained "); + } + string.push_str("fn("); + for (index, arg) in args.iter().enumerate() { + if index > 0 { + string.push_str(", "); + } + if index == 0 && has_self_type { + type_to_self_string(arg, &mut string); + } else { + string.push_str(&arg.to_string()); + } + } + string.push(')'); + + let ret: &Type = ret; + if let Type::Unit = ret { + // Nothing + } else { + string.push_str(" -> "); + string.push_str(&ret.to_string()); + } + string + } else { + typ.to_string() + } +} + +fn type_to_self_string(typ: &Type, string: &mut String) { + if let Type::MutableReference(..) = typ { + string.push_str("&mut self"); + } else { + string.push_str("self"); + } +} + +pub(super) fn struct_field_completion_item( + field: &str, + typ: &Type, + self_type: bool, +) -> CompletionItem { + field_completion_item(field, typ.to_string(), self_type) +} + +pub(super) fn field_completion_item( + field: &str, + typ: impl Into, + self_type: bool, +) -> CompletionItem { + if self_type { + simple_completion_item(format!("self.{field}"), CompletionItemKind::FIELD, Some(typ.into())) + } else { + simple_completion_item(field, CompletionItemKind::FIELD, Some(typ.into())) + } +} + +pub(super) fn simple_completion_item( + label: impl Into, + kind: CompletionItemKind, + description: Option, +) -> CompletionItem { + CompletionItem { + label: label.into(), + label_details: Some(CompletionItemLabelDetails { detail: None, description }), + kind: Some(kind), + detail: None, + documentation: None, + deprecated: None, + preselect: None, + sort_text: Some(default_sort_text()), + filter_text: None, + insert_text: None, + insert_text_format: None, + insert_text_mode: None, + text_edit: None, + additional_text_edits: None, + command: None, + commit_characters: None, + data: None, + tags: None, + } +} + +pub(super) fn snippet_completion_item( + label: impl Into, + kind: CompletionItemKind, + insert_text: impl Into, + description: Option, +) -> CompletionItem { + CompletionItem { + label: label.into(), + label_details: Some(CompletionItemLabelDetails { detail: None, description }), + kind: Some(kind), + insert_text_format: Some(InsertTextFormat::SNIPPET), + insert_text: Some(insert_text.into()), + detail: None, + documentation: None, + deprecated: None, + preselect: None, + sort_text: Some(default_sort_text()), + filter_text: None, + insert_text_mode: None, + text_edit: None, + additional_text_edits: None, + command: None, + commit_characters: None, + data: None, + tags: None, + } +} + +pub(super) fn completion_item_with_sort_text( + completion_item: CompletionItem, + sort_text: String, +) -> CompletionItem { + CompletionItem { sort_text: Some(sort_text), ..completion_item } +} + +pub(super) fn completion_item_with_trigger_parameter_hints_command( + completion_item: CompletionItem, +) -> CompletionItem { + CompletionItem { + command: Some(Command { + title: "Trigger parameter hints".to_string(), + command: "editor.action.triggerParameterHints".to_string(), + arguments: None, + }), + ..completion_item + } +} + +pub(super) fn completion_item_with_detail( + completion_item: CompletionItem, + detail: String, +) -> CompletionItem { + CompletionItem { detail: Some(detail), ..completion_item } +} diff --git a/tooling/lsp/src/requests/completion/kinds.rs b/tooling/lsp/src/requests/completion/kinds.rs new file mode 100644 index 00000000000..ba6faada6f4 --- /dev/null +++ b/tooling/lsp/src/requests/completion/kinds.rs @@ -0,0 +1,34 @@ +use noirc_frontend::{ast::AttributeTarget, Type}; + +/// When suggest a function as a result of completion, whether to autocomplete its name or its name and parameters. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(super) enum FunctionCompletionKind { + // Only complete a function's name. This is used in use statement. + Name, + // Complete a function's name and parameters (as a snippet). This is used in regular code. + NameAndParameters, +} + +/// Is there a requirement for suggesting functions? +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(super) enum FunctionKind<'a> { + /// No requirement: any function is okay to suggest. + Any, + /// Only show functions that have the given self type. + SelfType(&'a Type), +} + +/// When requesting completions, whether to list all items or just types. +/// For example, when writing `let x: S` we only want to suggest types at this +/// point (modules too, because they might include types too). +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub(super) enum RequestedItems { + // Suggest any items (types, functions, etc.). + AnyItems, + // Only suggest types (and modules, because they can contain types). + OnlyTypes, + // Only suggest traits (and modules, because they can contain traits). + OnlyTraits, + // Only attribute functions + OnlyAttributeFunctions(AttributeTarget), +} diff --git a/tooling/lsp/src/requests/completion/sort_text.rs b/tooling/lsp/src/requests/completion/sort_text.rs new file mode 100644 index 00000000000..9bdc603660f --- /dev/null +++ b/tooling/lsp/src/requests/completion/sort_text.rs @@ -0,0 +1,39 @@ +/// Sort text for "new" methods: we want these to show up before anything else, +/// if we are completing at something like `Foo::` +pub(super) fn new_sort_text() -> String { + "a".to_string() +} + +/// This is the default sort text. +pub(super) fn default_sort_text() -> String { + "b".to_string() +} + +/// We want crates and modules to show up after other things (for example +/// local variables, functions or types) +pub(super) fn crate_or_module_sort_text() -> String { + "c".to_string() +} + +/// Sort text for auto-import items. We want these to show up after local definitions. +pub(super) fn auto_import_sort_text() -> String { + "d".to_string() +} + +/// When completing something like `Foo::`, we want to show methods that take +/// self after the other ones. +pub(super) fn self_mismatch_sort_text() -> String { + "e".to_string() +} + +/// We want to show operator methods last. +pub(super) fn operator_sort_text() -> String { + "f".to_string() +} + +/// If a name begins with underscore it's likely something that's meant to +/// be private (but visibility doesn't exist everywhere yet, so for now +/// we assume that) +pub(super) fn underscore_sort_text() -> String { + "g".to_string() +} diff --git a/tooling/lsp/src/requests/completion/tests.rs b/tooling/lsp/src/requests/completion/tests.rs new file mode 100644 index 00000000000..e6cfebddb0c --- /dev/null +++ b/tooling/lsp/src/requests/completion/tests.rs @@ -0,0 +1,3025 @@ +#[cfg(test)] +mod completion_tests { + use crate::{ + notifications::on_did_open_text_document, + requests::{ + completion::{ + completion_items::{ + completion_item_with_detail, completion_item_with_sort_text, + completion_item_with_trigger_parameter_hints_command, module_completion_item, + simple_completion_item, snippet_completion_item, + trait_impl_method_completion_item, + }, + sort_text::{auto_import_sort_text, self_mismatch_sort_text}, + }, + on_completion_request, + }, + test_utils, + tests::apply_text_edits, + }; + + use lsp_types::{ + CompletionItem, CompletionItemKind, CompletionItemLabelDetails, CompletionParams, + CompletionResponse, DidOpenTextDocumentParams, PartialResultParams, Position, + TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams, + WorkDoneProgressParams, + }; + use tokio::test; + + async fn get_completions(src: &str) -> Vec { + let (mut state, noir_text_document) = test_utils::init_lsp_server("document_symbol").await; + + let (line, column) = src + .lines() + .enumerate() + .filter_map(|(line_index, line)| { + line.find(">|<").map(|char_index| (line_index, char_index)) + }) + .next() + .expect("Expected to find one >|< in the source code"); + + let src = src.replace(">|<", ""); + + on_did_open_text_document( + &mut state, + DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: noir_text_document.clone(), + language_id: "noir".to_string(), + version: 0, + text: src.to_string(), + }, + }, + ); + + let response = on_completion_request( + &mut state, + CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: noir_text_document }, + position: Position { line: line as u32, character: column as u32 }, + }, + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + partial_result_params: PartialResultParams { partial_result_token: None }, + context: None, + }, + ) + .await + .expect("Could not execute on_completion_request"); + + if let Some(CompletionResponse::Array(items)) = response { + items + } else { + vec![] + } + } + + fn assert_items_match(mut items: Vec, mut expected: Vec) { + items.sort_by_key(|item| item.label.clone()); + + expected.sort_by_key(|item| item.label.clone()); + + if items != expected { + println!( + "Items: {:?}", + items.iter().map(|item| item.label.clone()).collect::>() + ); + println!( + "Expected: {:?}", + expected.iter().map(|item| item.label.clone()).collect::>() + ); + } + + assert_eq!(items, expected); + } + + async fn assert_completion(src: &str, expected: Vec) { + let items = get_completions(src).await; + assert_items_match(items, expected); + } + + async fn assert_completion_excluding_auto_import(src: &str, expected: Vec) { + let items = get_completions(src).await; + let items = items.into_iter().filter(|item| item.additional_text_edits.is_none()).collect(); + assert_items_match(items, expected); + } + + pub(super) fn function_completion_item( + label: impl Into, + insert_text: impl Into, + description: impl Into, + ) -> CompletionItem { + let insert_text: String = insert_text.into(); + let description: String = description.into(); + + let has_arguments = insert_text.ends_with(')') && !insert_text.ends_with("()"); + let completion_item = if has_arguments { + completion_item_with_trigger_parameter_hints_command(snippet_completion_item( + label, + CompletionItemKind::FUNCTION, + insert_text, + Some(description.clone()), + )) + } else { + simple_completion_item(label, CompletionItemKind::FUNCTION, Some(description.clone())) + }; + + completion_item_with_detail(completion_item, description) + } + + fn field_completion_item(field: &str, typ: impl Into) -> CompletionItem { + crate::requests::completion::field_completion_item(field, typ, false) + } + + #[test] + async fn test_use_first_segment() { + let src = r#" + mod foobaz {} + mod foobar {} + use foob>|< + "#; + + assert_completion( + src, + vec![module_completion_item("foobaz"), module_completion_item("foobar")], + ) + .await; + } + + #[test] + async fn test_use_second_segment() { + let src = r#" + mod foo { + pub mod bar {} + pub mod baz {} + } + use foo::>|< + "#; + + assert_completion(src, vec![module_completion_item("bar"), module_completion_item("baz")]) + .await; + } + + #[test] + async fn test_use_second_segment_after_typing() { + let src = r#" + mod foo { + pub mod bar {} + pub mod brave {} + } + use foo::ba>|< + "#; + + assert_completion(src, vec![module_completion_item("bar")]).await; + } + + #[test] + async fn test_use_struct() { + let src = r#" + mod foo { + pub struct Foo {} + } + use foo::>|< + "#; + + assert_completion( + src, + vec![simple_completion_item( + "Foo", + CompletionItemKind::STRUCT, + Some("Foo".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_use_function() { + let src = r#" + mod foo { + pub fn bar(x: i32) -> u64 { 0 } + fn bar_is_private(x: i32) -> u64 { 0 } + } + use foo::>|< + "#; + + assert_completion(src, vec![function_completion_item("bar", "bar()", "fn(i32) -> u64")]) + .await; + } + + #[test] + async fn test_use_after_crate_and_letter() { + // Prove that "std" shows up + let src = r#" + use s>|< + "#; + assert_completion(src, vec![module_completion_item("std")]).await; + + // "std" doesn't show up anymore because of the "crate::" prefix + let src = r#" + mod something {} + use crate::s>|< + "#; + assert_completion(src, vec![module_completion_item("something")]).await; + } + + #[test] + async fn test_use_suggests_hardcoded_crate() { + let src = r#" + use cr>|< + "#; + + assert_completion( + src, + vec![simple_completion_item("crate::", CompletionItemKind::KEYWORD, None)], + ) + .await; + } + + #[test] + async fn test_use_in_tree_after_letter() { + let src = r#" + mod foo { + pub mod bar {} + } + use foo::{b>|<} + "#; + + assert_completion(src, vec![module_completion_item("bar")]).await; + } + + #[test] + async fn test_use_in_tree_after_colons() { + let src = r#" + mod foo { + pub mod bar { + pub mod baz {} + } + } + use foo::{bar::>|<} + "#; + + assert_completion(src, vec![module_completion_item("baz")]).await; + } + + #[test] + async fn test_use_in_tree_after_colons_after_another_segment() { + let src = r#" + mod foo { + pub mod bar {} + pub mod qux {} + } + use foo::{bar, q>|<} + "#; + + assert_completion(src, vec![module_completion_item("qux")]).await; + } + + #[test] + async fn test_use_in_nested_module() { + let src = r#" + mod foo { + mod something {} + + use s>|< + } + "#; + + assert_completion( + src, + vec![ + module_completion_item("something"), + module_completion_item("std"), + simple_completion_item("super::", CompletionItemKind::KEYWORD, None), + ], + ) + .await; + } + + #[test] + async fn test_use_after_super() { + let src = r#" + mod foobar {} + + mod bar { + mod something {} + + use super::foob>|< + } + "#; + + assert_completion(src, vec![module_completion_item("foobar")]).await; + } + + #[test] + async fn test_use_after_crate_and_letter_nested_in_module() { + let src = r#" + mod something { + mod something_else {} + use crate::s>|< + } + + "#; + assert_completion(src, vec![module_completion_item("something")]).await; + } + + #[test] + async fn test_use_after_crate_segment_and_letter_nested_in_module() { + let src = r#" + mod something { + mod something_else {} + use crate::something::s>|< + } + + "#; + assert_completion(src, vec![module_completion_item("something_else")]).await; + } + + #[test] + async fn test_complete_path_shows_module() { + let src = r#" + mod foobar {} + + fn main() { + fo>|< + } + "#; + assert_completion_excluding_auto_import(src, vec![module_completion_item("foobar")]).await; + } + + #[test] + async fn test_complete_path_after_colons_shows_submodule() { + let src = r#" + mod foo { + pub mod bar {} + } + + fn main() { + foo::>|< + } + "#; + assert_completion(src, vec![module_completion_item("bar")]).await; + } + + #[test] + async fn test_complete_path_after_colons_and_letter_shows_submodule() { + let src = r#" + mod foo { + pub mod qux {} + } + + fn main() { + foo::q>|< + } + "#; + assert_completion(src, vec![module_completion_item("qux")]).await; + } + + #[test] + async fn test_complete_path_with_local_variable() { + let src = r#" + fn main() { + let local = 1; + l>|< + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "local", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_complete_path_with_shadowed_local_variable() { + let src = r#" + fn main() { + let local = 1; + let local = true; + l>|< + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "local", + CompletionItemKind::VARIABLE, + Some("bool".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_complete_path_with_function_argument() { + let src = r#" + fn main(local: Field) { + l>|< + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "local", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_complete_type_path_with_non_empty_name() { + let src = r#" + trait One { + fn one() -> Self; + } + + impl One for Field { + fn one() -> Self { + 1 + } + } + + fn main() { + Field::o>|< + } + "#; + assert_completion(src, vec![function_completion_item("one()", "one()", "fn() -> Field")]) + .await; + } + + #[test] + async fn test_complete_function_without_arguments() { + let src = r#" + fn hello() { } + + fn main() { + h>|< + } + "#; + assert_completion_excluding_auto_import( + src, + vec![function_completion_item("hello()", "hello()", "fn()")], + ) + .await; + } + + #[test] + async fn test_complete_function() { + let src = r#" + fn hello(x: i32, y: Field) { } + + fn main() { + h>|< + } + "#; + assert_completion_excluding_auto_import( + src, + vec![function_completion_item( + "hello(…)", + "hello(${1:x}, ${2:y})", + "fn(i32, Field)".to_string(), + )], + ) + .await; + } + + #[test] + async fn test_complete_builtin_functions() { + let src = r#" + fn main() { + a>|< + } + "#; + assert_completion_excluding_auto_import( + src, + vec![ + completion_item_with_trigger_parameter_hints_command(snippet_completion_item( + "assert(…)", + CompletionItemKind::FUNCTION, + "assert(${1:predicate})", + Some("fn(T)".to_string()), + )), + function_completion_item("assert_constant(…)", "assert_constant(${1:x})", "fn(T)"), + completion_item_with_trigger_parameter_hints_command(snippet_completion_item( + "assert_eq(…)", + CompletionItemKind::FUNCTION, + "assert_eq(${1:lhs}, ${2:rhs})", + Some("fn(T, T)".to_string()), + )), + ], + ) + .await; + } + + #[test] + async fn test_complete_path_in_impl() { + let src = r#" + struct SomeStruct {} + + impl SomeStruct { + fn foo() { + So>|< + } + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "SomeStruct", + CompletionItemKind::STRUCT, + Some("SomeStruct".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_complete_path_in_trait_impl() { + let src = r#" + struct SomeStruct {} + trait Trait {} + + impl Trait for SomeStruct { + fn foo() { + So>|< + } + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "SomeStruct", + CompletionItemKind::STRUCT, + Some("SomeStruct".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_complete_path_with_for_argument() { + let src = r#" + fn main() { + for index in 0..10 { + ind>|< + } + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "index", + CompletionItemKind::VARIABLE, + Some("u32".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_complete_path_with_lambda_argument() { + let src = r#" + fn lambda(f: fn(i32)) { } + + fn main() { + lambda(|lambda_var| lambda_v>|<) + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "lambda_var", + CompletionItemKind::VARIABLE, + Some("i32".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_type_in_struct_field_type() { + let src = r#" + struct Something {} + + fn SomeFunction() {} + + struct Another { + some: So>|< + } + "#; + assert_completion( + src, + vec![simple_completion_item( + "Something", + CompletionItemKind::STRUCT, + Some("Something".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_type_in_function_parameter() { + let src = r#" + struct Something {} + + fn foo(x: So>|<) {} + "#; + assert_completion( + src, + vec![simple_completion_item( + "Something", + CompletionItemKind::STRUCT, + Some("Something".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_type_in_function_return_type() { + let src = r#" + struct Something {} + + fn foo() -> So>|< {} + "#; + assert_completion( + src, + vec![simple_completion_item( + "Something", + CompletionItemKind::STRUCT, + Some("Something".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_type_in_type_alias() { + let src = r#" + struct Something {} + + type Foo = So>|< + "#; + assert_completion( + src, + vec![simple_completion_item( + "Something", + CompletionItemKind::STRUCT, + Some("Something".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_type_in_trait_function() { + let src = r#" + struct Something {} + + trait Trait { + fn foo(s: So>|<); + } + "#; + assert_completion( + src, + vec![simple_completion_item( + "Something", + CompletionItemKind::STRUCT, + Some("Something".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_type_in_trait_function_return_type() { + let src = r#" + struct Something {} + + trait Trait { + fn foo() -> So>|<; + } + "#; + assert_completion( + src, + vec![simple_completion_item( + "Something", + CompletionItemKind::STRUCT, + Some("Something".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_type_in_let_type() { + let src = r#" + struct Something {} + + fn main() { + let x: So>|< + } + "#; + assert_completion( + src, + vec![simple_completion_item( + "Something", + CompletionItemKind::STRUCT, + Some("Something".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_type_in_lambda_parameter() { + let src = r#" + struct Something {} + + fn main() { + foo(|s: So>|<| s) + } + "#; + assert_completion( + src, + vec![simple_completion_item( + "Something", + CompletionItemKind::STRUCT, + Some("Something".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_builtin_types() { + let src = r#" + fn foo(x: i>|<) {} + "#; + + let items = get_completions(src).await; + let items = items.into_iter().filter(|item| item.label.starts_with('i')).collect(); + + assert_items_match( + items, + vec![ + simple_completion_item("i8", CompletionItemKind::STRUCT, Some("i8".to_string())), + simple_completion_item("i16", CompletionItemKind::STRUCT, Some("i16".to_string())), + simple_completion_item("i32", CompletionItemKind::STRUCT, Some("i32".to_string())), + simple_completion_item("i64", CompletionItemKind::STRUCT, Some("i64".to_string())), + ], + ); + } + + #[test] + async fn test_suggest_builtin_types_in_any_position() { + let src = r#" + fn foo() { + i>|< + } + "#; + + let items = get_completions(src).await; + assert!(items.iter().any(|item| item.label == "i8")); + } + + #[test] + async fn test_suggest_true() { + let src = r#" + fn main() { + let x = t>|< + } + "#; + + let items = get_completions(src).await; + assert!(items + .iter() + .any(|item| item.label == "true" && item.kind == Some(CompletionItemKind::KEYWORD))); + } + + #[test] + async fn test_suggest_regarding_if_scope() { + let src = r#" + fn main() { + let good = 1; + if true { + let great = 2; + g>|< + } else { + let greater = 3; + } + } + "#; + assert_completion_excluding_auto_import( + src, + vec![ + simple_completion_item( + "good", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + ), + simple_completion_item( + "great", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + ), + ], + ) + .await; + + let src = r#" + fn main() { + let good = 1; + if true { + let great = 2; + } else { + let greater = 3; + g>|< + } + } + "#; + assert_completion_excluding_auto_import( + src, + vec![ + simple_completion_item( + "good", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + ), + simple_completion_item( + "greater", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + ), + ], + ) + .await; + + let src = r#" + fn main() { + let good = 1; + if true { + let great = 2; + } else { + let greater = 3; + } + g>|< + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "good", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_regarding_block_scope() { + let src = r#" + fn main() { + let good = 1; + { + let great = 2; + g>|< + } + } + "#; + assert_completion_excluding_auto_import( + src, + vec![ + simple_completion_item( + "good", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + ), + simple_completion_item( + "great", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + ), + ], + ) + .await; + + let src = r#" + fn main() { + let good = 1; + { + let great = 2; + } + g>|< + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "good", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggest_struct_type_parameter() { + let src = r#" + struct Foo { + context: Cont>|< + } + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item("Context", CompletionItemKind::TYPE_PARAMETER, None)], + ) + .await; + } + + #[test] + async fn test_suggest_impl_type_parameter() { + let src = r#" + struct Foo {} + + impl Foo { + fn foo() { + let x: TypeP>|< + } + } + "#; + assert_completion( + src, + vec![simple_completion_item("TypeParam", CompletionItemKind::TYPE_PARAMETER, None)], + ) + .await; + } + + #[test] + async fn test_suggest_trait_impl_type_parameter() { + let src = r#" + struct Foo {} + trait Trait {} + + impl Trait for Foo { + fn foo() { + let x: TypeP>|< + } + } + "#; + assert_completion( + src, + vec![simple_completion_item("TypeParam", CompletionItemKind::TYPE_PARAMETER, None)], + ) + .await; + } + + #[test] + async fn test_suggest_trait_function_type_parameter() { + let src = r#" + struct Foo {} + trait Trait { + fn foo() { + let x: TypeP>|< + } + } + "#; + assert_completion( + src, + vec![simple_completion_item("TypeParam", CompletionItemKind::TYPE_PARAMETER, None)], + ) + .await; + } + + #[test] + async fn test_suggest_function_type_parameters() { + let src = r#" + fn foo(x: Cont>|<) {} + "#; + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item("Context", CompletionItemKind::TYPE_PARAMETER, None)], + ) + .await; + } + + #[test] + async fn test_suggests_struct_field_after_dot_and_letter() { + let src = r#" + struct Some { + property: i32, + } + + fn foo(s: Some) { + s.p>|< + } + "#; + assert_completion(src, vec![field_completion_item("property", "i32")]).await; + } + + #[test] + async fn test_suggests_struct_field_after_dot_and_letter_for_generic_type() { + let src = r#" + struct Some { + property: T, + } + + fn foo(s: Some) { + s.p>|< + } + "#; + assert_completion(src, vec![field_completion_item("property", "i32")]).await; + } + + #[test] + async fn test_suggests_struct_field_after_dot_followed_by_brace() { + let src = r#" + struct Some { + property: i32, + } + + fn foo(s: Some) { + s.>|< + } + "#; + assert_completion(src, vec![field_completion_item("property", "i32")]).await; + } + + #[test] + async fn test_suggests_struct_field_after_dot_chain() { + let src = r#" + struct Some { + property: Other, + } + + struct Other { + bar: i32, + } + + fn foo(some: Some) { + some.property.>|< + } + "#; + assert_completion(src, vec![field_completion_item("bar", "i32")]).await; + } + + #[test] + async fn test_does_not_suggest_private_struct_field() { + let src = r#" + mod moo { + pub struct Some { + property: i32, + } + } + + fn foo(s: moo::Some) { + s.>|< + } + "#; + assert_completion(src, vec![]).await; + } + + #[test] + async fn test_suggests_struct_impl_method() { + let src = r#" + struct Some { + } + + impl Some { + fn foobar(self, x: i32) {} + fn foobar2(&mut self, x: i32) {} + fn foobar3(y: i32) {} + } + + fn foo(some: Some) { + some.f>|< + } + "#; + assert_completion( + src, + vec![ + function_completion_item("foobar(…)", "foobar(${1:x})", "fn(self, i32)"), + function_completion_item("foobar2(…)", "foobar2(${1:x})", "fn(&mut self, i32)"), + ], + ) + .await; + } + + #[test] + async fn test_suggests_struct_trait_impl_method() { + let src = r#" + struct Some { + } + + trait SomeTrait { + fn foobar(self, x: i32); + fn foobar2(y: i32); + } + + impl SomeTrait for Some { + fn foobar(self, x: i32) {} + fn foobar2(y: i32) {} + } + + fn foo(some: Some) { + some.f>|< + } + "#; + assert_completion( + src, + vec![function_completion_item("foobar(…)", "foobar(${1:x})", "fn(self, i32)")], + ) + .await; + } + + #[test] + async fn test_suggests_primitive_trait_impl_method() { + let src = r#" + trait SomeTrait { + fn foobar(self, x: i32); + fn foobar2(y: i32); + } + + impl SomeTrait for Field { + fn foobar(self, x: i32) {} + fn foobar2(y: i32) {} + } + + fn foo(field: Field) { + field.f>|< + } + "#; + assert_completion( + src, + vec![function_completion_item("foobar(…)", "foobar(${1:x})", "fn(self, i32)")], + ) + .await; + } + + #[test] + async fn test_suggests_struct_methods_after_colons() { + let src = r#" + struct Some { + } + + impl Some { + fn foobar(self, x: i32) {} + fn foobar2(&mut self, x: i32) {} + fn foobar3(y: i32) {} + } + + fn foo() { + Some::>|< + } + "#; + assert_completion( + src, + vec![ + completion_item_with_sort_text( + function_completion_item( + "foobar(…)", + "foobar(${1:self}, ${2:x})", + "fn(self, i32)", + ), + self_mismatch_sort_text(), + ), + completion_item_with_sort_text( + function_completion_item( + "foobar2(…)", + "foobar2(${1:self}, ${2:x})", + "fn(&mut self, i32)", + ), + self_mismatch_sort_text(), + ), + function_completion_item("foobar3(…)", "foobar3(${1:y})", "fn(i32)"), + ], + ) + .await; + } + + #[test] + async fn test_suggests_struct_behind_alias_methods_after_dot() { + let src = r#" + struct Some { + } + + type Alias = Some; + + impl Some { + fn foobar(self, x: i32) {} + } + + fn foo(some: Alias) { + some.>|< + } + "#; + assert_completion( + src, + vec![function_completion_item("foobar(…)", "foobar(${1:x})", "fn(self, i32)")], + ) + .await; + } + + #[test] + async fn test_suggests_struct_behind_alias_methods_after_colons() { + let src = r#" + struct Some { + } + + type Alias = Some; + + impl Some { + fn foobar(self, x: i32) {} + fn foobar2(&mut self, x: i32) {} + fn foobar3(y: i32) {} + } + + fn foo() { + Alias::>|< + } + "#; + assert_completion( + src, + vec![ + completion_item_with_sort_text( + function_completion_item( + "foobar(…)", + "foobar(${1:self}, ${2:x})", + "fn(self, i32)", + ), + self_mismatch_sort_text(), + ), + completion_item_with_sort_text( + function_completion_item( + "foobar2(…)", + "foobar2(${1:self}, ${2:x})", + "fn(&mut self, i32)", + ), + self_mismatch_sort_text(), + ), + function_completion_item("foobar3(…)", "foobar3(${1:y})", "fn(i32)"), + ], + ) + .await; + } + + #[test] + async fn test_completes_in_broken_if_after_dot() { + let src = r#" + struct Some { + foo: i32, + } + + fn foo(s: Some) { + if s.>|< + } + "#; + assert_completion(src, vec![field_completion_item("foo", "i32")]).await; + } + + #[test] + async fn test_completes_in_nested_expression() { + let src = r#" + struct Foo { bar: Bar } + struct Bar { baz: i32 } + + fn foo(f: Foo) { + f.bar & f.>|< + } + "#; + assert_completion(src, vec![field_completion_item("bar", "Bar")]).await; + } + + #[test] + async fn test_completes_in_call_chain() { + let src = r#" + struct Foo {} + + impl Foo { + fn foo(self) -> Foo { self } + } + + fn foo(f: Foo) { + f.foo().>|< + } + "#; + assert_completion(src, vec![function_completion_item("foo()", "foo()", "fn(self) -> Foo")]) + .await; + } + + #[test] + async fn test_completes_when_assignment_follows() { + let src = r#" + struct Foo { + bar: i32, + } + + fn foo(f: Foo) { + let mut x = 1; + + f.>|< + + x = 2; + } + "#; + assert_completion(src, vec![field_completion_item("bar", "i32")]).await; + } + + #[test] + async fn test_completes_tuple_fields() { + let src = r#" + fn main() { + let tuple = (1, true); + tuple.>|< + } + "#; + + let items = get_completions(src).await; + let items = items.into_iter().filter(|item| item.kind == Some(CompletionItemKind::FIELD)); + let items = items.collect(); + + assert_items_match( + items, + vec![field_completion_item("0", "Field"), field_completion_item("1", "bool")], + ); + } + + #[test] + async fn test_completes_constructor_fields() { + let src = r#" + mod foobar { + struct Foo { + bb: i32, + bbb: Field, + bbbb: bool, + bbbbb: str<6>, + } + } + + fn main() { + foobar::Foo { bbb: 1, b>|<, bbbbb } + } + "#; + assert_completion( + src, + vec![field_completion_item("bb", "i32"), field_completion_item("bbbb", "bool")], + ) + .await; + } + + #[test] + async fn test_completes_trait_methods() { + let src = r#" + trait One { + fn one() -> Self; + } + + fn main() { + One::>|< + } + "#; + assert_completion(src, vec![function_completion_item("one()", "one()", "fn() -> Self")]) + .await; + } + + #[test] + async fn test_auto_imports() { + let src = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + + struct Foo { + } + + impl Foo { + // This is here to make sure it's not offered for completion + fn hello_world() {} + } + } +} + +fn main() { + hel>|< +} + "#; + + let expected = r#"use foo::bar::hello_world; + +mod foo { + pub mod bar { + pub fn hello_world() {} + + struct Foo { + } + + impl Foo { + // This is here to make sure it's not offered for completion + fn hello_world() {} + } + } +} + +fn main() { + hel +} + "#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + assert_eq!(item.label, "hello_world()"); + assert_eq!( + item.label_details, + Some(CompletionItemLabelDetails { + detail: Some("(use foo::bar::hello_world)".to_string()), + description: Some("fn()".to_string()) + }) + ); + + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_when_in_nested_module_and_item_is_further_nested() { + let src = r#"#[something] +mod foo { + pub mod bar { + pub fn hello_world() {} + } + + fn foo() { + hel>|< + } +} + "#; + + let expected = r#"#[something] +mod foo { + use bar::hello_world; + + pub mod bar { + pub fn hello_world() {} + } + + fn foo() { + hel + } +} + "#; + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + assert_eq!(item.label, "hello_world()"); + assert_eq!( + item.label_details, + Some(CompletionItemLabelDetails { + detail: Some("(use bar::hello_world)".to_string()), + description: Some("fn()".to_string()) + }) + ); + + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + } + + #[test] + async fn test_auto_imports_when_in_nested_module_and_item_is_not_further_nested() { + let src = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } + + pub mod baz { + fn foo() { + hel>|< + } + } +}"#; + + let expected = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } + + pub mod baz { + use super::bar::hello_world; + + fn foo() { + hel + } + } +}"#; + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + assert_eq!(item.label, "hello_world()"); + assert_eq!( + item.label_details, + Some(CompletionItemLabelDetails { + detail: Some("(use super::bar::hello_world)".to_string()), + description: Some("fn()".to_string()) + }) + ); + + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + } + + #[test] + async fn test_auto_import_inserts_after_last_use() { + let src = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } +} + +mod baz { + fn qux() {} +} + +use baz::qux; + +fn main() { + hel>|< +}"#; + + let expected = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } +} + +mod baz { + fn qux() {} +} + +use baz::qux; +use foo::bar::hello_world; + +fn main() { + hel +}"#; + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + } + + #[test] + async fn test_auto_import_inserts_after_last_use_in_nested_module() { + let src = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } +} + +mod baz { + fn qux() {} +} + +mod other { + use baz::qux; + + fn main() { + hel>|< + } +}"#; + + let expected = r#"mod foo { + pub mod bar { + pub fn hello_world() {} + } +} + +mod baz { + fn qux() {} +} + +mod other { + use baz::qux; + use super::foo::bar::hello_world; + + fn main() { + hel + } +}"#; + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + } + + #[test] + async fn test_does_not_auto_import_test_functions() { + let src = r#" + mod foo { + mod bar { + #[test] + pub fn hello_world() {} + } + } + + use foo::bar; + + fn main() { + hel>|< + } + "#; + let items = get_completions(src).await; + assert!(items.is_empty()); + } + + #[test] + async fn test_does_not_auto_import_private_functions() { + let src = r#" + mod foo { + mod bar { + fn hello_world() {} + } + } + + use foo::bar; + + fn main() { + hel>|< + } + "#; + let items = get_completions(src).await; + assert!(items.is_empty()); + } + + #[test] + async fn test_does_not_auto_import_public_function_in_private_module() { + let src = r#" + mod foo { + mod bar { + pub fn hello_world() {} + } + } + + fn main() { + hel>|< + } + "#; + let items = get_completions(src).await; + assert!(items.is_empty()); + } + + #[test] + async fn checks_visibility_of_module_that_exports_item_if_any() { + let src = r#" + mod foo { + mod bar { + pub fn hello_world() {} + } + + pub use bar::hello_world; + } + + fn main() { + hello_w>|< + } + "#; + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + assert_eq!(item.label, "hello_world()"); + assert_eq!(item.label_details.unwrap().detail.unwrap(), "(use foo::hello_world)"); + } + + #[test] + async fn test_auto_import_suggests_modules_too() { + let src = r#"mod foo { + pub mod barbaz { + fn hello_world() {} + } + } + + fn main() { + barb>|< + } +}"#; + + let expected = r#"use foo::barbaz; + +mod foo { + pub mod barbaz { + fn hello_world() {} + } + } + + fn main() { + barb + } +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + assert_eq!(item.label, "barbaz"); + + assert_eq!( + item.label_details, + Some(CompletionItemLabelDetails { + detail: Some("(use foo::barbaz)".to_string()), + description: None + }) + ); + + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_one_segment_not_in_list() { + let src = r#"use foo::bar::one_hello_world; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{one_hello_world, two_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_two_segments() { + let src = r#"use foo::bar::one_hello_world; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + } + pub fn two_hello_world() {} +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::{bar::one_hello_world, two_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + } + pub fn two_hello_world() {} +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_one_segment_inside_list() { + let src = r#"use foo::{bar::one_hello_world, baz}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } + pub mod baz {} +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::{bar::{one_hello_world, two_hello_world}, baz}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } + pub mod baz {} +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_one_segment_checks_parents() { + let src = r#"use foo::bar::baz; + +mod foo { + pub mod bar { + pub mod baz { + pub fn one_hello_world() {} + } + pub mod qux { + pub fn two_hello_world() {} + } + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{baz, qux::two_hello_world}; + +mod foo { + pub mod bar { + pub mod baz { + pub fn one_hello_world() {} + } + pub mod qux { + pub fn two_hello_world() {} + } + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_last_segment() { + let src = r#"use foo::bar; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{self, two_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_list() { + let src = r#"use foo::bar::{one_hello_world, three_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + pub fn three_hello_world() {} + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{two_hello_world, one_hello_world, three_hello_world}; + +mod foo { + pub mod bar { + pub fn one_hello_world() {} + pub fn two_hello_world() {} + pub fn three_hello_world() {} + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_auto_imports_expands_existing_use_before_empty_list() { + let src = r#"use foo::bar::{}; + +mod foo { + pub mod bar { + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_>|< +}"#; + + let expected = r#"use foo::bar::{two_hello_world}; + +mod foo { + pub mod bar { + pub fn two_hello_world() {} + } +} + +fn main() { + two_hello_ +}"#; + + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + let changed = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + assert_eq!(changed, expected); + assert_eq!(item.sort_text, Some(auto_import_sort_text())); + } + + #[test] + async fn test_completes_matching_any_part_of_an_identifier_by_underscore() { + let src = r#" + struct Foo { + some_property: i32, + } + + fn foo(f: Foo) { + f.prop>|< + } + "#; + assert_completion(src, vec![field_completion_item("some_property", "i32")]).await; + } + + #[test] + async fn test_completes_in_impl_type() { + let src = r#" + struct FooBar { + } + + impl FooB>|< + "#; + + assert_completion( + src, + vec![simple_completion_item( + "FooBar", + CompletionItemKind::STRUCT, + Some("FooBar".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_completes_in_impl_for_type() { + let src = r#" + struct FooBar { + } + + impl Default for FooB>|< + "#; + + assert_completion( + src, + vec![simple_completion_item( + "FooBar", + CompletionItemKind::STRUCT, + Some("FooBar".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_auto_import_with_super() { + let src = r#" + pub fn bar_baz() {} + + mod tests { + fn foo() { + bar_b>|< + } + } + "#; + let items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = &items[0]; + assert_eq!(item.label, "bar_baz()"); + assert_eq!( + item.label_details, + Some(CompletionItemLabelDetails { + detail: Some("(use super::bar_baz)".to_string()), + description: Some("fn()".to_string()) + }) + ); + } + + #[test] + async fn test_auto_import_from_std() { + let src = r#" + fn main() { + compute_merkle_roo>|< + } + "#; + let items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = &items[0]; + assert_eq!(item.label, "compute_merkle_root(…)"); + assert_eq!( + item.label_details.as_ref().unwrap().detail, + Some("(use std::merkle::compute_merkle_root)".to_string()), + ); + } + + #[test] + async fn test_completes_after_first_letter_of_path() { + let src = r#" + fn main() { + h>||||||<() + } + "#; + assert_completion_excluding_auto_import( + src, + vec![function_completion_item("bar", "bar()", "fn(self)")], + ) + .await; + } + + #[test] + async fn test_does_not_suggest_private_struct_methods() { + let src = r#" + mod moo { + pub struct Foo {} + + impl Foo { + fn bar(self) {} + } + } + + fn x(f: moo::Foo) { + f.>|<() + } + "#; + assert_completion(src, vec![]).await; + } + + #[test] + async fn test_does_not_suggest_private_primitive_methods() { + let src = r#" + fn foo(x: Field) { + x.>|< + } + "#; + let items = get_completions(src).await; + if items.iter().any(|item| item.label == "__assert_max_bit_size") { + panic!("Private method __assert_max_bit_size was suggested"); + } + } + + #[test] + async fn test_suggests_pub_use() { + let src = r#" + mod bar { + pub mod baz { + pub mod coco {} + } + + pub use baz::coco; + } + + fn main() { + bar::c>|< + } + "#; + assert_completion(src, vec![module_completion_item("coco")]).await; + } + + #[test] + async fn test_auto_import_suggests_pub_use_for_module() { + let src = r#" + mod bar { + pub mod baz { + pub mod coco {} + } + + pub use baz::coco as foobar; + } + + fn main() { + foob>|< + } + "#; + + let items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = &items[0]; + assert_eq!(item.label, "foobar"); + assert_eq!( + item.label_details.as_ref().unwrap().detail, + Some("(use bar::foobar)".to_string()), + ); + } + + #[test] + async fn test_auto_import_suggests_pub_use_for_function() { + let src = r#" + mod bar { + pub mod baz { + pub fn coco() {} + } + + pub use baz::coco as foobar; + } + + fn main() { + foob>|< + } + "#; + + let items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = &items[0]; + assert_eq!(item.label, "foobar()"); + assert_eq!( + item.label_details.as_ref().unwrap().detail, + Some("(use bar::foobar)".to_string()), + ); + } + + #[test] + async fn test_auto_import_suggests_private_function_if_visibile() { + let src = r#" + mod foo { + fn qux() { + barba>|< + } + } + + fn barbaz() {} + + fn main() {} + "#; + + let items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = &items[0]; + assert_eq!(item.label, "barbaz()"); + assert_eq!( + item.label_details.as_ref().unwrap().detail, + Some("(use super::barbaz)".to_string()), + ); + } + + #[test] + async fn test_suggests_self_fields_and_methods() { + let src = r#" + struct Foo { + foobar: Field, + } + + impl Foo { + fn foobarbaz(self) {} + + fn some_method(self) { + foob>|< + } + } + "#; + + assert_completion_excluding_auto_import( + src, + vec![ + field_completion_item("self.foobar", "Field"), + function_completion_item("self.foobarbaz()", "self.foobarbaz()", "fn(self)"), + ], + ) + .await; + } + + #[test] + async fn test_suggests_built_in_function_attribute() { + let src = r#" + #[no_pred>|<] + fn foo() {} + "#; + + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item("no_predicates", CompletionItemKind::METHOD, None)], + ) + .await; + } + + #[test] + async fn test_suggests_built_in_let_attribute() { + let src = r#" + fn foo() { + #[allo>|<] + let x = 1; + } + "#; + + assert_completion_excluding_auto_import( + src, + vec![simple_completion_item( + "allow(unused_variables)", + CompletionItemKind::METHOD, + None, + )], + ) + .await; + } + + #[test] + async fn test_suggests_function_attribute() { + let src = r#" + #[some>|<] + fn foo() {} + + comptime fn some_attr(f: FunctionDefinition, x: Field) -> Quoted {} + fn some_other_function(x: Field) {} + "#; + + assert_completion_excluding_auto_import( + src, + vec![function_completion_item( + "some_attr(…)", + "some_attr(${1:x})", + "fn(FunctionDefinition, Field) -> Quoted", + )], + ) + .await; + } + + #[test] + async fn test_suggests_function_attribute_no_arguments() { + let src = r#" + #[some>|<] + fn foo() {} + + fn some_attr(f: FunctionDefinition) {} + "#; + + assert_completion_excluding_auto_import( + src, + vec![function_completion_item("some_attr", "some_attr", "fn(FunctionDefinition)")], + ) + .await; + } + + #[test] + async fn test_suggests_trait_attribute() { + let src = r#" + #[some>|<] + trait SomeTrait {} + + fn some_attr(t: TraitDefinition, x: Field) {} + "#; + + assert_completion_excluding_auto_import( + src, + vec![function_completion_item( + "some_attr(…)", + "some_attr(${1:x})", + "fn(TraitDefinition, Field)", + )], + ) + .await; + } + + #[test] + async fn test_suggests_trait_impl_function() { + let src = r#" + trait Trait { + fn foo(x: i32) -> i32; + } + + struct Foo {} + + impl Trait for Foo { + fn f>|< + }"#; + + assert_completion( + src, + vec![trait_impl_method_completion_item( + "fn foo(..)", + "foo(x: i32) -> i32 {\n ${1}\n}", + )], + ) + .await; + } + + #[test] + async fn test_suggests_trait_impl_default_function() { + let src = r#" + trait Trait { + fn foo(x: i32) -> i32 { 1 } + } + + struct Foo {} + + impl Trait for Foo { + fn f>|< + }"#; + + assert_completion( + src, + vec![trait_impl_method_completion_item( + "fn foo(..)", + "foo(x: i32) -> i32 {\n ${1}\n}", + )], + ) + .await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_1() { + let src = r#" + struct Foo { + bar: Bar + } + + struct Bar { + baz: Field + } + + fn f(foo: Foo) { + let mut x = 1; + + foo.bar.>|< + + x = 2; + }"#; + + assert_completion(src, vec![field_completion_item("baz", "Field")]).await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_2() { + let src = r#" + struct Foo { + bar: Bar + } + + struct Bar { + baz: Baz + } + + struct Baz { + qux: Field + } + + fn f(foo: Foo) { + let mut x = 1; + + foo.bar.baz.>|< + + x = 2; + }"#; + + assert_completion(src, vec![field_completion_item("qux", "Field")]).await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_3() { + let src = r#" + struct Foo { + foo: Field + } + + fn execute() { + let a = Foo { foo: 1 }; + a.>|< + + x = 1; + }"#; + + assert_completion(src, vec![field_completion_item("foo", "Field")]).await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_4() { + let src = r#" + struct Foo { + bar: Bar + } + + struct Bar { + baz: Field + } + + fn execute() { + let foo = Foo { foo: 1 }; + foo.bar.>|< + + x = 1; + }"#; + + assert_completion(src, vec![field_completion_item("baz", "Field")]).await; + } + + #[test] + async fn test_suggests_when_assignment_follows_in_chain_with_index() { + let src = r#" + struct Foo { + bar: Field + } + + fn f(foos: [Foo; 3]) { + let mut x = 1; + + foos[0].>|< + + x = 2; + }"#; + + assert_completion(src, vec![field_completion_item("bar", "Field")]).await; + } + + #[test] + async fn test_suggests_macro_call_if_comptime_function_returns_quoted() { + let src = r#" + comptime fn foobar() -> Quoted {} + + fn main() { + comptime { + fooba>|< + } + } + "#; + + assert_completion_excluding_auto_import( + src, + vec![ + function_completion_item("foobar!()", "foobar!()", "fn() -> Quoted"), + function_completion_item("foobar()", "foobar()", "fn() -> Quoted"), + ], + ) + .await; + } + + #[test] + async fn test_suggests_only_macro_call_if_comptime_function_returns_quoted_and_outside_comptime( + ) { + let src = r#" + comptime fn foobar() -> Quoted {} + + fn main() { + fooba>|< + } + "#; + + assert_completion_excluding_auto_import( + src, + vec![function_completion_item("foobar!()", "foobar!()", "fn() -> Quoted")], + ) + .await; + } + + #[test] + async fn test_only_suggests_macro_call_for_unquote() { + let src = r#" + use std::meta::unquote; + + fn main() { + unquot>|< + } + "#; + + let completions = get_completions(src).await; + assert_eq!(completions.len(), 1); + assert_eq!(completions[0].label, "unquote!(…)"); + } + + #[test] + async fn test_suggests_variable_in_quoted_after_dollar() { + let src = r#" + fn main() { + comptime { + let some_var = 1; + quote { + $>|< + } + } + } + "#; + + assert_completion( + src, + vec![simple_completion_item( + "some_var", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggests_variable_in_quoted_after_dollar_and_letters() { + let src = r#" + fn main() { + comptime { + let some_var = 1; + quote { + $s>|< + } + } + } + "#; + + assert_completion( + src, + vec![simple_completion_item( + "some_var", + CompletionItemKind::VARIABLE, + Some("Field".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_does_not_auto_import_private_global() { + let src = r#"mod moo { + global foobar = 1; + } + + fn main() { + fooba>|< + }"#; + + assert_completion(src, Vec::new()).await; + } + + #[test] + async fn test_does_not_auto_import_private_type_alias() { + let src = r#"mod moo { + type foobar = i32; + } + + fn main() { + fooba>|< + }"#; + + assert_completion(src, Vec::new()).await; + } + + #[test] + async fn test_does_not_auto_import_private_trait() { + let src = r#"mod moo { + trait Foobar {} + } + + fn main() { + Fooba>|< + }"#; + + assert_completion(src, Vec::new()).await; + } + + #[test] + async fn test_does_not_auto_import_private_module() { + let src = r#"mod moo { + mod foobar {} + } + + fn main() { + fooba>|< + }"#; + + assert_completion(src, Vec::new()).await; + } + + #[test] + async fn test_suggests_trait_in_trait_parent_bounds() { + let src = r#" + trait Foobar {} + struct Foobarbaz {} + + trait Bar: Foob>|< {} + "#; + assert_completion( + src, + vec![simple_completion_item( + "Foobar", + CompletionItemKind::INTERFACE, + Some("Foobar".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggests_trait_in_function_where_clause() { + let src = r#" + trait Foobar {} + struct Foobarbaz {} + + fn foo() where T: Foob>|< {} + "#; + assert_completion( + src, + vec![simple_completion_item( + "Foobar", + CompletionItemKind::INTERFACE, + Some("Foobar".to_string()), + )], + ) + .await; + } + + #[test] + async fn test_suggests_methods_based_on_type_generics() { + let src = r#" + struct Foo { + t: T, + } + + impl Foo { + fn bar_baz(_self: Self) -> Field { + 5 + } + } + + impl Foo { + fn bar(_self: Self) -> Field { + 5 + } + + fn baz(_self: Self) -> Field { + 6 + } + } + + fn main() -> pub Field { + let foo: Foo = Foo { t: 5 }; + foo.b>|< + } + "#; + let items = get_completions(src).await; + assert_eq!(items.len(), 1); + assert!(items[0].label == "bar_baz()"); + } + + #[test] + async fn test_suggests_trait_method_from_where_clause_in_function() { + let src = r#" + trait Foo { + fn foo(self) -> i32; + } + + fn something(x: T) -> i32 + where + T: Foo, + { + x.fo>|< + } + "#; + let items = get_completions(src).await; + assert_eq!(items.len(), 1); + } + + #[test] + async fn test_does_not_suggest_trait_function_not_visible() { + let src = r#" + mod moo { + trait Foo { + fn foobar(); + } + + impl Foo for Field { + fn foobar() {} + } + } + + fn main() { + Field::fooba>|< + } + + "#; + assert_completion(src, vec![]).await; + } + + #[test] + async fn test_suggests_multiple_trait_methods() { + let src = r#" + mod moo { + pub trait Foo { + fn foobar(); + } + + impl Foo for Field { + fn foobar() {} + } + + pub trait Bar { + fn foobar(); + } + + impl Bar for Field { + fn foobar() {} + } + } + + fn main() { + Field::fooba>|< + } + + "#; + let items = get_completions(src).await; + assert_eq!(items.len(), 2); + } + + #[test] + async fn test_suggests_and_imports_trait_method_without_self() { + let src = r#" +mod moo { + pub trait Foo { + fn foobar(); + } + + impl Foo for Field { + fn foobar() {} + } +} + +fn main() { + Field::fooba>|< +} + "#; + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + assert_eq!(item.label_details.unwrap().detail, Some("(use moo::Foo)".to_string())); + + let new_code = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + + let expected = r#"use moo::Foo; + +mod moo { + pub trait Foo { + fn foobar(); + } + + impl Foo for Field { + fn foobar() {} + } +} + +fn main() { + Field::fooba +} + "#; + assert_eq!(new_code, expected); + } + + #[test] + async fn test_suggests_and_imports_trait_method_with_self() { + let src = r#" +mod moo { + pub trait Foo { + fn foobar(self); + } + + impl Foo for Field { + fn foobar(self) {} + } +} + +fn main() { + let x: Field = 1; + x.fooba>|< +} + "#; + let mut items = get_completions(src).await; + assert_eq!(items.len(), 1); + + let item = items.remove(0); + assert_eq!(item.label_details.unwrap().detail, Some("(use moo::Foo)".to_string())); + + let new_code = + apply_text_edits(&src.replace(">|<", ""), &item.additional_text_edits.unwrap()); + + let expected = r#"use moo::Foo; + +mod moo { + pub trait Foo { + fn foobar(self); + } + + impl Foo for Field { + fn foobar(self) {} + } +} + +fn main() { + let x: Field = 1; + x.fooba +} + "#; + assert_eq!(new_code, expected); + } +} diff --git a/tooling/lsp/src/requests/document_symbol.rs b/tooling/lsp/src/requests/document_symbol.rs new file mode 100644 index 00000000000..0fc2dc4622e --- /dev/null +++ b/tooling/lsp/src/requests/document_symbol.rs @@ -0,0 +1,777 @@ +use std::future::{self, Future}; + +use async_lsp::ResponseError; +use fm::{FileId, FileMap, PathString}; +use lsp_types::{ + DocumentSymbol, DocumentSymbolParams, DocumentSymbolResponse, Location, Position, SymbolKind, + TextDocumentPositionParams, +}; +use noirc_errors::Span; +use noirc_frontend::{ + ast::{ + Expression, FunctionReturnType, Ident, LetStatement, NoirFunction, NoirStruct, NoirTrait, + NoirTraitImpl, TypeImpl, UnresolvedType, Visitor, + }, + parser::ParsedSubModule, + ParsedModule, +}; + +use crate::LspState; + +use super::process_request; + +pub(crate) fn on_document_symbol_request( + state: &mut LspState, + params: DocumentSymbolParams, +) -> impl Future, ResponseError>> { + let Ok(file_path) = params.text_document.uri.to_file_path() else { + return future::ready(Ok(None)); + }; + + let text_document_position_params = TextDocumentPositionParams { + text_document: params.text_document.clone(), + position: Position { line: 0, character: 0 }, + }; + + let result = process_request(state, text_document_position_params, |args| { + args.files.get_file_id(&PathString::from_path(file_path)).map(|file_id| { + let file = args.files.get_file(file_id).unwrap(); + let source = file.source(); + let (parsed_module, _errors) = noirc_frontend::parse_program(source); + + let mut collector = DocumentSymbolCollector::new(file_id, args.files); + let symbols = collector.collect(&parsed_module); + DocumentSymbolResponse::Nested(symbols) + }) + }); + + future::ready(result) +} + +struct DocumentSymbolCollector<'a> { + file_id: FileId, + files: &'a FileMap, + symbols: Vec, +} + +impl<'a> DocumentSymbolCollector<'a> { + fn new(file_id: FileId, files: &'a FileMap) -> Self { + Self { file_id, files, symbols: Vec::new() } + } + + fn collect(&mut self, parsed_module: &ParsedModule) -> Vec { + parsed_module.accept(self); + + std::mem::take(&mut self.symbols) + } + + fn collect_in_type(&mut self, name: &Ident, typ: Option<&UnresolvedType>) { + if name.0.contents.is_empty() { + return; + } + + let Some(name_location) = self.to_lsp_location(name.span()) else { + return; + }; + + let span = if let Some(typ) = typ { + Span::from(name.span().start()..typ.span.end()) + } else { + name.span() + }; + + let Some(location) = self.to_lsp_location(span) else { + return; + }; + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name: name.to_string(), + detail: None, + kind: SymbolKind::TYPE_PARAMETER, + tags: None, + deprecated: None, + range: location.range, + selection_range: name_location.range, + children: None, + }); + } + + fn collect_in_constant( + &mut self, + name: &Ident, + typ: &UnresolvedType, + default_value: Option<&Expression>, + ) { + if name.0.contents.is_empty() { + return; + } + + let Some(name_location) = self.to_lsp_location(name.span()) else { + return; + }; + + let mut span = name.span(); + + // If there's a type span, extend the span to include it + span = Span::from(span.start()..typ.span.end()); + + // If there's a default value, extend the span to include it + if let Some(default_value) = default_value { + span = Span::from(span.start()..default_value.span.end()); + } + + let Some(location) = self.to_lsp_location(span) else { + return; + }; + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name: name.to_string(), + detail: None, + kind: SymbolKind::CONSTANT, + tags: None, + deprecated: None, + range: location.range, + selection_range: name_location.range, + children: None, + }); + } + + fn to_lsp_location(&self, span: Span) -> Option { + super::to_lsp_location(self.files, self.file_id, span) + } +} + +impl<'a> Visitor for DocumentSymbolCollector<'a> { + fn visit_noir_function(&mut self, noir_function: &NoirFunction, span: Span) -> bool { + if noir_function.def.name.0.contents.is_empty() { + return false; + } + + let Some(location) = self.to_lsp_location(span) else { + return false; + }; + + let Some(selection_location) = self.to_lsp_location(noir_function.name_ident().span()) + else { + return false; + }; + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name: noir_function.name().to_string(), + detail: Some(noir_function.def.signature()), + kind: SymbolKind::FUNCTION, + tags: None, + deprecated: None, + range: location.range, + selection_range: selection_location.range, + children: None, + }); + + false + } + + fn visit_noir_struct(&mut self, noir_struct: &NoirStruct, span: Span) -> bool { + if noir_struct.name.0.contents.is_empty() { + return false; + } + + let Some(location) = self.to_lsp_location(span) else { + return false; + }; + + let Some(selection_location) = self.to_lsp_location(noir_struct.name.span()) else { + return false; + }; + + let mut children = Vec::new(); + for field in &noir_struct.fields { + let field_name = &field.item.name; + let typ = &field.item.typ; + let span = Span::from(field_name.span().start()..typ.span.end()); + + let Some(field_location) = self.to_lsp_location(span) else { + continue; + }; + + let Some(field_name_location) = self.to_lsp_location(field_name.span()) else { + continue; + }; + + #[allow(deprecated)] + children.push(DocumentSymbol { + name: field_name.to_string(), + detail: None, + kind: SymbolKind::FIELD, + tags: None, + deprecated: None, + range: field_location.range, + selection_range: field_name_location.range, + children: None, + }); + } + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name: noir_struct.name.to_string(), + detail: None, + kind: SymbolKind::STRUCT, + tags: None, + deprecated: None, + range: location.range, + selection_range: selection_location.range, + children: Some(children), + }); + + false + } + + fn visit_noir_trait(&mut self, noir_trait: &NoirTrait, span: Span) -> bool { + if noir_trait.name.0.contents.is_empty() { + return false; + } + + let Some(location) = self.to_lsp_location(span) else { + return false; + }; + + let Some(selection_location) = self.to_lsp_location(noir_trait.name.span()) else { + return false; + }; + + let old_symbols = std::mem::take(&mut self.symbols); + self.symbols = Vec::new(); + + for item in &noir_trait.items { + item.item.accept(self); + } + + let children = std::mem::take(&mut self.symbols); + self.symbols = old_symbols; + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name: noir_trait.name.to_string(), + detail: None, + kind: SymbolKind::INTERFACE, + tags: None, + deprecated: None, + range: location.range, + selection_range: selection_location.range, + children: Some(children), + }); + + false + } + + fn visit_trait_item_function( + &mut self, + name: &Ident, + _generics: &noirc_frontend::ast::UnresolvedGenerics, + parameters: &[(Ident, UnresolvedType)], + return_type: &FunctionReturnType, + _where_clause: &[noirc_frontend::ast::UnresolvedTraitConstraint], + body: &Option, + ) -> bool { + if name.0.contents.is_empty() { + return false; + } + + let Some(name_location) = self.to_lsp_location(name.span()) else { + return false; + }; + + let mut span = name.span(); + + // If there are parameters, extend the span to include the last parameter. + if let Some((param_name, _param_type)) = parameters.last() { + span = Span::from(span.start()..param_name.span().end()); + } + + // If there's a return type, extend the span to include it + match return_type { + FunctionReturnType::Default(return_type_span) => { + span = Span::from(span.start()..return_type_span.end()); + } + FunctionReturnType::Ty(typ) => { + span = Span::from(span.start()..typ.span.end()); + } + } + + // If there's a body, extend the span to include it + if let Some(body) = body { + if let Some(statement) = body.statements.last() { + span = Span::from(span.start()..statement.span.end()); + } + } + + let Some(location) = self.to_lsp_location(span) else { + return false; + }; + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name: name.to_string(), + detail: None, + kind: SymbolKind::METHOD, + tags: None, + deprecated: None, + range: location.range, + selection_range: name_location.range, + children: None, + }); + + false + } + + fn visit_trait_item_constant( + &mut self, + name: &Ident, + typ: &UnresolvedType, + default_value: &Option, + ) -> bool { + if name.0.contents.is_empty() { + return false; + } + + self.collect_in_constant(name, typ, default_value.as_ref()); + false + } + + fn visit_trait_item_type(&mut self, name: &Ident) { + self.collect_in_type(name, None); + } + + fn visit_noir_trait_impl(&mut self, noir_trait_impl: &NoirTraitImpl, span: Span) -> bool { + let Some(location) = self.to_lsp_location(span) else { + return false; + }; + + let Some(name_location) = self.to_lsp_location(noir_trait_impl.trait_name.span) else { + return false; + }; + + let mut trait_name = String::new(); + trait_name.push_str(&noir_trait_impl.trait_name.to_string()); + if !noir_trait_impl.trait_generics.is_empty() { + trait_name.push('<'); + for (index, generic) in noir_trait_impl.trait_generics.ordered_args.iter().enumerate() { + if index > 0 { + trait_name.push_str(", "); + } + trait_name.push_str(&generic.to_string()); + } + for (index, (name, generic)) in + noir_trait_impl.trait_generics.named_args.iter().enumerate() + { + if index > 0 { + trait_name.push_str(", "); + } + trait_name.push_str(&name.0.contents); + trait_name.push_str(" = "); + trait_name.push_str(&generic.to_string()); + } + trait_name.push('>'); + } + + let old_symbols = std::mem::take(&mut self.symbols); + self.symbols = Vec::new(); + + for trait_impl_item in &noir_trait_impl.items { + trait_impl_item.item.accept(self); + } + + let children = std::mem::take(&mut self.symbols); + self.symbols = old_symbols; + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name: format!("impl {} for {}", trait_name, noir_trait_impl.object_type), + detail: None, + kind: SymbolKind::NAMESPACE, + tags: None, + deprecated: None, + range: location.range, + selection_range: name_location.range, + children: Some(children), + }); + + false + } + + fn visit_trait_impl_item_constant( + &mut self, + name: &Ident, + typ: &UnresolvedType, + default_value: &Expression, + _span: Span, + ) -> bool { + self.collect_in_constant(name, typ, Some(default_value)); + false + } + + fn visit_trait_impl_item_type( + &mut self, + name: &Ident, + alias: &UnresolvedType, + _span: Span, + ) -> bool { + self.collect_in_type(name, Some(alias)); + false + } + + fn visit_type_impl(&mut self, type_impl: &TypeImpl, span: Span) -> bool { + let Some(location) = self.to_lsp_location(span) else { + return false; + }; + + let name = type_impl.object_type.typ.to_string(); + if name.is_empty() { + return false; + } + + let Some(name_location) = self.to_lsp_location(type_impl.object_type.span) else { + return false; + }; + + let old_symbols = std::mem::take(&mut self.symbols); + self.symbols = Vec::new(); + + for (noir_function, noir_function_span) in &type_impl.methods { + noir_function.item.accept(*noir_function_span, self); + } + + let children = std::mem::take(&mut self.symbols); + self.symbols = old_symbols; + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name: name.to_string(), + detail: None, + kind: SymbolKind::NAMESPACE, + tags: None, + deprecated: None, + range: location.range, + selection_range: name_location.range, + children: Some(children), + }); + + false + } + + fn visit_parsed_submodule(&mut self, parsed_sub_module: &ParsedSubModule, span: Span) -> bool { + if parsed_sub_module.name.0.contents.is_empty() { + return false; + } + + let Some(name_location) = self.to_lsp_location(parsed_sub_module.name.span()) else { + return false; + }; + + let Some(location) = self.to_lsp_location(span) else { + return false; + }; + + let old_symbols = std::mem::take(&mut self.symbols); + self.symbols = Vec::new(); + + for item in &parsed_sub_module.contents.items { + item.accept(self); + } + + let children = std::mem::take(&mut self.symbols); + self.symbols = old_symbols; + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name: parsed_sub_module.name.to_string(), + detail: None, + kind: SymbolKind::MODULE, + tags: None, + deprecated: None, + range: location.range, + selection_range: name_location.range, + children: Some(children), + }); + + false + } + + fn visit_global(&mut self, global: &LetStatement, span: Span) -> bool { + let name = global.pattern.to_string(); + if name.is_empty() { + return false; + } + + let Some(name_location) = self.to_lsp_location(global.pattern.span()) else { + return false; + }; + + let Some(location) = self.to_lsp_location(span) else { + return false; + }; + + #[allow(deprecated)] + self.symbols.push(DocumentSymbol { + name, + detail: None, + kind: SymbolKind::CONSTANT, + tags: None, + deprecated: None, + range: location.range, + selection_range: name_location.range, + children: None, + }); + + false + } +} + +#[cfg(test)] +mod document_symbol_tests { + use crate::test_utils; + + use super::*; + use lsp_types::{ + PartialResultParams, Range, SymbolKind, TextDocumentIdentifier, WorkDoneProgressParams, + }; + use tokio::test; + + #[test] + async fn test_document_symbol() { + let (mut state, noir_text_document) = test_utils::init_lsp_server("document_symbol").await; + + let response = on_document_symbol_request( + &mut state, + DocumentSymbolParams { + text_document: TextDocumentIdentifier { uri: noir_text_document }, + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + partial_result_params: PartialResultParams { partial_result_token: None }, + }, + ) + .await + .expect("Could not execute on_document_symbol_request") + .unwrap(); + + let DocumentSymbolResponse::Nested(symbols) = response else { + panic!("Expected response to be nested"); + }; + + assert_eq!( + symbols, + vec![ + #[allow(deprecated)] + DocumentSymbol { + name: "foo".to_string(), + detail: Some("fn foo(_x: i32)".to_string()), + kind: SymbolKind::FUNCTION, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 0, character: 0 }, + end: Position { line: 2, character: 1 }, + }, + selection_range: Range { + start: Position { line: 0, character: 3 }, + end: Position { line: 0, character: 6 }, + }, + children: None, + }, + #[allow(deprecated)] + DocumentSymbol { + name: "SomeStruct".to_string(), + detail: None, + kind: SymbolKind::STRUCT, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 4, character: 0 }, + end: Position { line: 6, character: 1 }, + }, + selection_range: Range { + start: Position { line: 4, character: 7 }, + end: Position { line: 4, character: 17 }, + }, + children: Some(vec![ + #[allow(deprecated)] + DocumentSymbol { + name: "field".to_string(), + detail: None, + kind: SymbolKind::FIELD, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 5, character: 4 }, + end: Position { line: 5, character: 14 }, + }, + selection_range: Range { + start: Position { line: 5, character: 4 }, + end: Position { line: 5, character: 9 }, + }, + children: None, + }, + ],), + }, + #[allow(deprecated)] + DocumentSymbol { + name: "SomeStruct".to_string(), + detail: None, + kind: SymbolKind::NAMESPACE, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 8, character: 0 }, + end: Position { line: 12, character: 1 }, + }, + selection_range: Range { + start: Position { line: 8, character: 5 }, + end: Position { line: 8, character: 15 }, + }, + children: Some(vec![ + #[allow(deprecated)] + DocumentSymbol { + name: "new".to_string(), + detail: Some("fn new() -> SomeStruct".to_string()), + kind: SymbolKind::FUNCTION, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 9, character: 4 }, + end: Position { line: 11, character: 5 }, + }, + selection_range: Range { + start: Position { line: 9, character: 7 }, + end: Position { line: 9, character: 10 }, + }, + children: None, + }, + ],), + }, + #[allow(deprecated)] + DocumentSymbol { + name: "SomeTrait".to_string(), + detail: None, + kind: SymbolKind::INTERFACE, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 14, character: 0 }, + end: Position { line: 16, character: 1 }, + }, + selection_range: Range { + start: Position { line: 14, character: 6 }, + end: Position { line: 14, character: 15 }, + }, + children: Some(vec![ + #[allow(deprecated)] + DocumentSymbol { + name: "some_method".to_string(), + detail: None, + kind: SymbolKind::METHOD, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 15, character: 7 }, + end: Position { line: 15, character: 24 }, + }, + selection_range: Range { + start: Position { line: 15, character: 7 }, + end: Position { line: 15, character: 18 }, + }, + children: None, + }, + ],), + }, + #[allow(deprecated)] + DocumentSymbol { + name: "impl SomeTrait for SomeStruct".to_string(), + detail: None, + kind: SymbolKind::NAMESPACE, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 18, character: 0 }, + end: Position { line: 21, character: 1 }, + }, + selection_range: Range { + start: Position { line: 18, character: 5 }, + end: Position { line: 18, character: 14 }, + }, + children: Some(vec![ + #[allow(deprecated)] + DocumentSymbol { + name: "some_method".to_string(), + detail: Some("fn some_method(_x: i32)".to_string()), + kind: SymbolKind::FUNCTION, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 19, character: 4 }, + end: Position { line: 20, character: 5 }, + }, + selection_range: Range { + start: Position { line: 19, character: 7 }, + end: Position { line: 19, character: 18 }, + }, + children: None, + }, + ],), + }, + #[allow(deprecated)] + DocumentSymbol { + name: "submodule".to_string(), + detail: None, + kind: SymbolKind::MODULE, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 23, character: 0 }, + end: Position { line: 25, character: 1 }, + }, + selection_range: Range { + start: Position { line: 23, character: 4 }, + end: Position { line: 23, character: 13 }, + }, + children: Some(vec![ + #[allow(deprecated)] + DocumentSymbol { + name: "SOME_GLOBAL".to_string(), + detail: None, + kind: SymbolKind::CONSTANT, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 24, character: 4 }, + end: Position { line: 24, character: 27 } + }, + selection_range: Range { + start: Position { line: 24, character: 11 }, + end: Position { line: 24, character: 22 } + }, + children: None + } + ]), + }, + #[allow(deprecated)] + DocumentSymbol { + name: "i32".to_string(), + detail: None, + kind: SymbolKind::NAMESPACE, + tags: None, + deprecated: None, + range: Range { + start: Position { line: 27, character: 0 }, + end: Position { line: 27, character: 11 } + }, + selection_range: Range { + start: Position { line: 27, character: 5 }, + end: Position { line: 27, character: 8 } + }, + children: Some(Vec::new()) + } + ] + ); + } +} diff --git a/tooling/lsp/src/requests/goto_declaration.rs b/tooling/lsp/src/requests/goto_declaration.rs new file mode 100644 index 00000000000..bd0f0afb827 --- /dev/null +++ b/tooling/lsp/src/requests/goto_declaration.rs @@ -0,0 +1,31 @@ +use std::future::{self, Future}; + +use crate::types::GotoDeclarationResult; +use crate::LspState; +use async_lsp::ResponseError; + +use lsp_types::request::{GotoDeclarationParams, GotoDeclarationResponse}; + +use super::{process_request, to_lsp_location}; + +pub(crate) fn on_goto_declaration_request( + state: &mut LspState, + params: GotoDeclarationParams, +) -> impl Future> { + let result = on_goto_definition_inner(state, params); + future::ready(result) +} + +fn on_goto_definition_inner( + state: &mut LspState, + params: GotoDeclarationParams, +) -> Result { + process_request(state, params.text_document_position_params, |args| { + args.interner.get_declaration_location_from(args.location).and_then(|found_location| { + let file_id = found_location.file; + let definition_position = to_lsp_location(args.files, file_id, found_location.span)?; + 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 new file mode 100644 index 00000000000..a2443ea165d --- /dev/null +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -0,0 +1,290 @@ +use std::future::{self, Future}; + +use crate::attribute_reference_finder::AttributeReferenceFinder; +use crate::utils; +use crate::{types::GotoDefinitionResult, LspState}; +use async_lsp::ResponseError; + +use fm::PathString; +use lsp_types::request::GotoTypeDefinitionParams; +use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse}; + +use super::{process_request, to_lsp_location}; + +pub(crate) fn on_goto_definition_request( + state: &mut LspState, + params: GotoDefinitionParams, +) -> impl Future> { + let result = on_goto_definition_inner(state, params, false); + future::ready(result) +} + +pub(crate) fn on_goto_type_definition_request( + state: &mut LspState, + params: GotoTypeDefinitionParams, +) -> impl Future> { + let result = on_goto_definition_inner(state, params, true); + future::ready(result) +} + +fn on_goto_definition_inner( + state: &mut LspState, + params: GotoDefinitionParams, + return_type_location_instead: bool, +) -> Result { + let uri = params.text_document_position_params.text_document.uri.clone(); + let position = params.text_document_position_params.position; + process_request(state, params.text_document_position_params, |args| { + let path = PathString::from_path(uri.to_file_path().unwrap()); + let reference_id = args.files.get_file_id(&path).and_then(|file_id| { + utils::position_to_byte_index(args.files, file_id, &position).and_then(|byte_index| { + let file = args.files.get_file(file_id).unwrap(); + let source = file.source(); + let (parsed_module, _errors) = noirc_frontend::parse_program(source); + + let mut finder = AttributeReferenceFinder::new( + file_id, + byte_index, + args.crate_id, + args.def_maps, + ); + finder.find(&parsed_module) + }) + }); + let location = if let Some(reference_id) = reference_id { + Some(args.interner.reference_location(reference_id)) + } else { + args.interner + .get_definition_location_from(args.location, return_type_location_instead) + .or_else(|| { + args.interner + .reference_at_location(args.location) + .map(|reference| args.interner.reference_location(reference)) + }) + }; + location.and_then(|found_location| { + let file_id = found_location.file; + let definition_position = to_lsp_location(args.files, file_id, found_location.span)?; + let response = GotoDefinitionResponse::from(definition_position).to_owned(); + Some(response) + }) + }) +} + +#[cfg(test)] +mod goto_definition_tests { + use std::panic; + + use crate::test_utils::{self, search_in_file}; + use lsp_types::{Position, Range}; + use tokio::test; + + use super::*; + + async fn expect_goto_for_all_references(directory: &str, name: &str, definition_index: usize) { + let (mut state, noir_text_document) = test_utils::init_lsp_server(directory).await; + + let ranges = search_in_file(noir_text_document.path(), name); + let expected_range = ranges[definition_index]; + + for (index, range) in ranges.iter().enumerate() { + // Ideally "go to" at the definition should return the same location, but this isn't currently + // working. But it's also not that important, so we'll keep it for later. + if index == definition_index { + continue; + } + + let params = GotoDefinitionParams { + text_document_position_params: lsp_types::TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { + uri: noir_text_document.clone(), + }, + position: range.start, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }; + + let response = on_goto_definition_request(&mut state, params) + .await + .expect("Could execute on_goto_definition_request") + .unwrap_or_else(|| { + panic!("Didn't get a goto definition response for index {index}") + }); + + if let GotoDefinitionResponse::Scalar(location) = response { + assert_eq!(location.range, expected_range); + } else { + panic!("Expected a scalar response"); + }; + } + } + + async fn expect_goto( + directory: &str, + position: Position, + expected_file: &str, + expected_range: Range, + ) { + let (mut state, noir_text_document) = test_utils::init_lsp_server(directory).await; + + let params = GotoDefinitionParams { + text_document_position_params: lsp_types::TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { + uri: noir_text_document.clone(), + }, + position, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }; + + let response = on_goto_definition_request(&mut state, params) + .await + .expect("Could execute on_goto_definition_request") + .unwrap_or_else(|| panic!("Didn't get a goto definition response")); + + if let GotoDefinitionResponse::Scalar(location) = response { + assert!(location.uri.to_string().ends_with(expected_file)); + assert_eq!(location.range, expected_range); + } else { + panic!("Expected a scalar response"); + }; + } + + #[test] + async fn goto_from_function_location_to_declaration() { + expect_goto_for_all_references("go_to_definition", "another_function", 0).await; + } + + #[test] + async fn goto_from_use_as() { + expect_goto( + "go_to_definition", + Position { line: 7, character: 29 }, // The word after `as`, + "src/main.nr", + Range { + start: Position { line: 1, character: 11 }, + end: Position { line: 1, character: 27 }, + }, + ) + .await; + } + + #[test] + async fn goto_module_from_call_path() { + expect_goto( + "go_to_definition", + Position { line: 17, character: 4 }, // "bar" in "bar::baz()" + "src/bar.nr", + Range { + start: Position { line: 0, character: 0 }, + end: Position { line: 0, character: 0 }, + }, + ) + .await; + } + + #[test] + async fn goto_inline_module_from_call_path() { + expect_goto( + "go_to_definition", + Position { line: 18, character: 9 }, // "inline" in "bar::inline::qux()" + "src/bar.nr", + Range { + start: Position { line: 2, character: 4 }, + end: Position { line: 2, character: 10 }, + }, + ) + .await; + } + + #[test] + async fn goto_module_from_use_path() { + expect_goto( + "go_to_definition", + Position { line: 6, character: 4 }, // "foo" in "use foo::another_function;" + "src/main.nr", + Range { + start: Position { line: 0, character: 4 }, + end: Position { line: 0, character: 7 }, + }, + ) + .await; + } + + #[test] + async fn goto_module_from_mod() { + expect_goto( + "go_to_definition", + Position { line: 9, character: 4 }, // "bar" in "mod bar;" + "src/bar.nr", + Range { + start: Position { line: 0, character: 0 }, + end: Position { line: 0, character: 0 }, + }, + ) + .await; + } + + #[test] + async fn goto_for_local_variable() { + expect_goto_for_all_references("local_variable", "some_var", 0).await; + } + + #[test] + async fn goto_at_struct_definition_finds_same_struct() { + expect_goto( + "go_to_definition", + Position { line: 21, character: 7 }, // "Foo" in "struct Foo" + "src/main.nr", + Range { + start: Position { line: 21, character: 7 }, + end: Position { line: 21, character: 10 }, + }, + ) + .await; + } + + #[test] + async fn goto_at_trait_definition_finds_same_trait() { + expect_goto( + "go_to_definition", + Position { line: 25, character: 6 }, // "Trait" in "trait Trait" + "src/main.nr", + Range { + start: Position { line: 25, character: 6 }, + end: Position { line: 25, character: 11 }, + }, + ) + .await; + } + + #[test] + async fn goto_crate() { + expect_goto( + "go_to_definition", + Position { line: 29, character: 6 }, // "dependency" in "use dependency::something" + "dependency/src/lib.nr", + Range { + start: Position { line: 0, character: 0 }, + end: Position { line: 0, character: 0 }, + }, + ) + .await; + } + + #[test] + async fn goto_attribute_function() { + expect_goto( + "go_to_definition", + Position { line: 31, character: 3 }, // "attr" + "src/main.nr", + Range { + start: Position { line: 34, character: 12 }, + end: Position { line: 34, character: 16 }, + }, + ) + .await; + } +} diff --git a/tooling/lsp/src/requests/hover.rs b/tooling/lsp/src/requests/hover.rs new file mode 100644 index 00000000000..ef1246d752d --- /dev/null +++ b/tooling/lsp/src/requests/hover.rs @@ -0,0 +1,1171 @@ +use std::future::{self, Future}; + +use async_lsp::ResponseError; +use fm::{FileMap, PathString}; +use lsp_types::{Hover, HoverContents, HoverParams, MarkupContent, MarkupKind}; +use noirc_frontend::{ + ast::{ItemVisibility, Visibility}, + hir::def_map::ModuleId, + hir_def::{ + expr::{HirArrayLiteral, HirExpression, HirLiteral}, + function::FuncMeta, + stmt::HirPattern, + traits::Trait, + }, + node_interner::{ + DefinitionId, DefinitionKind, ExprId, FuncId, GlobalId, NodeInterner, ReferenceId, + StructId, TraitId, TraitImplKind, TypeAliasId, + }, + Generics, Shared, StructType, Type, TypeAlias, TypeBinding, TypeVariable, +}; + +use crate::{ + attribute_reference_finder::AttributeReferenceFinder, modules::module_full_path, utils, + LspState, +}; + +use super::{process_request, to_lsp_location, ProcessRequestCallbackArgs}; + +pub(crate) fn on_hover_request( + state: &mut LspState, + params: HoverParams, +) -> impl Future, ResponseError>> { + let uri = params.text_document_position_params.text_document.uri.clone(); + let position = params.text_document_position_params.position; + let result = process_request(state, params.text_document_position_params, |args| { + let path = PathString::from_path(uri.to_file_path().unwrap()); + args.files + .get_file_id(&path) + .and_then(|file_id| { + utils::position_to_byte_index(args.files, file_id, &position).and_then( + |byte_index| { + let file = args.files.get_file(file_id).unwrap(); + let source = file.source(); + let (parsed_module, _errors) = noirc_frontend::parse_program(source); + + let mut finder = AttributeReferenceFinder::new( + file_id, + byte_index, + args.crate_id, + args.def_maps, + ); + finder.find(&parsed_module) + }, + ) + }) + .or_else(|| args.interner.reference_at_location(args.location)) + .and_then(|reference| { + let location = args.interner.reference_location(reference); + let lsp_location = to_lsp_location(args.files, location.file, location.span); + format_reference(reference, &args).map(|formatted| Hover { + range: lsp_location.map(|location| location.range), + contents: HoverContents::Markup(MarkupContent { + kind: MarkupKind::Markdown, + value: formatted, + }), + }) + }) + }); + + future::ready(result) +} + +fn format_reference(reference: ReferenceId, args: &ProcessRequestCallbackArgs) -> Option { + match reference { + ReferenceId::Module(id) => format_module(id, args), + ReferenceId::Struct(id) => Some(format_struct(id, args)), + ReferenceId::StructMember(id, field_index) => { + Some(format_struct_member(id, field_index, args)) + } + ReferenceId::Trait(id) => Some(format_trait(id, args)), + ReferenceId::Global(id) => Some(format_global(id, args)), + ReferenceId::Function(id) => Some(format_function(id, args)), + ReferenceId::Alias(id) => Some(format_alias(id, args)), + ReferenceId::Local(id) => Some(format_local(id, args)), + ReferenceId::Reference(location, _) => { + format_reference(args.interner.find_referenced(location).unwrap(), args) + } + } +} +fn format_module(id: ModuleId, args: &ProcessRequestCallbackArgs) -> Option { + let crate_root = args.def_maps[&id.krate].root(); + + let mut string = String::new(); + + if id.local_id == crate_root { + let dep = args.dependencies.iter().find(|dep| dep.crate_id == id.krate)?; + string.push_str(" crate "); + string.push_str(&dep.name.to_string()); + } else { + // Note: it's not clear why `try_module_attributes` might return None here, but it happens. + // This is a workaround to avoid panicking in that case (which brings the LSP server down). + // Cases where this happens are related to generated code, so once that stops happening + // this won't be an issue anymore. + let module_attributes = args.interner.try_module_attributes(&id)?; + + if let Some(parent_local_id) = module_attributes.parent { + if format_parent_module_from_module_id( + &ModuleId { krate: id.krate, local_id: parent_local_id }, + args, + &mut string, + ) { + string.push('\n'); + } + } + string.push_str(" "); + string.push_str("mod "); + string.push_str(&module_attributes.name); + } + + append_doc_comments(args.interner, ReferenceId::Module(id), &mut string); + + Some(string) +} + +fn format_struct(id: StructId, args: &ProcessRequestCallbackArgs) -> String { + let struct_type = args.interner.get_struct(id); + let struct_type = struct_type.borrow(); + + let mut string = String::new(); + if format_parent_module(ReferenceId::Struct(id), args, &mut string) { + string.push('\n'); + } + string.push_str(" "); + string.push_str("struct "); + string.push_str(&struct_type.name.0.contents); + format_generics(&struct_type.generics, &mut string); + string.push_str(" {\n"); + for field in struct_type.get_fields_as_written() { + string.push_str(" "); + string.push_str(&field.name.0.contents); + string.push_str(": "); + string.push_str(&format!("{}", field.typ)); + string.push_str(",\n"); + } + string.push_str(" }"); + + append_doc_comments(args.interner, ReferenceId::Struct(id), &mut string); + + string +} + +fn format_struct_member( + id: StructId, + field_index: usize, + args: &ProcessRequestCallbackArgs, +) -> String { + let struct_type = args.interner.get_struct(id); + let struct_type = struct_type.borrow(); + let field = struct_type.field_at(field_index); + + let mut string = String::new(); + if format_parent_module(ReferenceId::Struct(id), args, &mut string) { + string.push_str("::"); + } + string.push_str(&struct_type.name.0.contents); + string.push('\n'); + string.push_str(" "); + string.push_str(&field.name.0.contents); + string.push_str(": "); + string.push_str(&format!("{}", field.typ)); + string.push_str(&go_to_type_links(&field.typ, args.interner, args.files)); + + append_doc_comments(args.interner, ReferenceId::StructMember(id, field_index), &mut string); + + string +} + +fn format_trait(id: TraitId, args: &ProcessRequestCallbackArgs) -> String { + let a_trait = args.interner.get_trait(id); + + let mut string = String::new(); + if format_parent_module(ReferenceId::Trait(id), args, &mut string) { + string.push('\n'); + } + string.push_str(" "); + string.push_str("trait "); + string.push_str(&a_trait.name.0.contents); + format_generics(&a_trait.generics, &mut string); + + append_doc_comments(args.interner, ReferenceId::Trait(id), &mut string); + + string +} + +fn format_global(id: GlobalId, args: &ProcessRequestCallbackArgs) -> String { + let global_info = args.interner.get_global(id); + let definition_id = global_info.definition_id; + let definition = args.interner.definition(definition_id); + let typ = args.interner.definition_type(definition_id); + + let mut string = String::new(); + if format_parent_module(ReferenceId::Global(id), args, &mut string) { + string.push('\n'); + } + + let mut print_comptime = definition.comptime; + let mut opt_value = None; + + // See if we can figure out what's the global's value + if let Some(stmt) = args.interner.get_global_let_statement(id) { + print_comptime = stmt.comptime; + opt_value = get_global_value(args.interner, stmt.expression); + } + + string.push_str(" "); + if print_comptime { + string.push_str("comptime "); + } + if definition.mutable { + string.push_str("mut "); + } + string.push_str("global "); + string.push_str(&global_info.ident.0.contents); + string.push_str(": "); + string.push_str(&format!("{}", typ)); + + if let Some(value) = opt_value { + string.push_str(" = "); + string.push_str(&value); + } + + string.push_str(&go_to_type_links(&typ, args.interner, args.files)); + + append_doc_comments(args.interner, ReferenceId::Global(id), &mut string); + + string +} + +fn get_global_value(interner: &NodeInterner, expr: ExprId) -> Option { + match interner.expression(&expr) { + HirExpression::Literal(literal) => match literal { + HirLiteral::Array(hir_array_literal) => { + get_global_array_value(interner, hir_array_literal, false) + } + HirLiteral::Slice(hir_array_literal) => { + get_global_array_value(interner, hir_array_literal, true) + } + HirLiteral::Bool(value) => Some(value.to_string()), + HirLiteral::Integer(field_element, _) => Some(field_element.to_string()), + HirLiteral::Str(string) => Some(format!("{:?}", string)), + HirLiteral::FmtStr(..) => None, + HirLiteral::Unit => Some("()".to_string()), + }, + HirExpression::Tuple(values) => { + get_exprs_global_value(interner, &values).map(|value| format!("({})", value)) + } + _ => None, + } +} + +fn get_global_array_value( + interner: &NodeInterner, + literal: HirArrayLiteral, + is_slice: bool, +) -> Option { + match literal { + HirArrayLiteral::Standard(values) => { + get_exprs_global_value(interner, &values).map(|value| { + if is_slice { + format!("&[{}]", value) + } else { + format!("[{}]", value) + } + }) + } + HirArrayLiteral::Repeated { repeated_element, length } => { + get_global_value(interner, repeated_element).map(|value| { + if is_slice { + format!("&[{}; {}]", value, length) + } else { + format!("[{}; {}]", value, length) + } + }) + } + } +} + +fn get_exprs_global_value(interner: &NodeInterner, exprs: &[ExprId]) -> Option { + let strings: Vec = + exprs.iter().filter_map(|value| get_global_value(interner, *value)).collect(); + if strings.len() == exprs.len() { + Some(strings.join(", ")) + } else { + None + } +} + +fn format_function(id: FuncId, args: &ProcessRequestCallbackArgs) -> String { + let func_meta = args.interner.function_meta(&id); + + // If this points to a trait method, see if we can figure out what's the concrete trait impl method + if let Some(func_id) = get_trait_impl_func_id(id, args, func_meta) { + return format_function(func_id, args); + } + + let func_modifiers = args.interner.function_modifiers(&id); + + let func_name_definition_id = args.interner.definition(func_meta.name.id); + + let mut string = String::new(); + let formatted_parent_module = + format_parent_module(ReferenceId::Function(id), args, &mut string); + + let formatted_parent_type = if let Some(trait_impl_id) = func_meta.trait_impl { + let trait_impl = args.interner.get_trait_implementation(trait_impl_id); + let trait_impl = trait_impl.borrow(); + let trait_ = args.interner.get_trait(trait_impl.trait_id); + + let generics: Vec<_> = + trait_impl + .trait_generics + .iter() + .filter_map(|generic| { + if let Type::NamedGeneric(_, name) = generic { + Some(name) + } else { + None + } + }) + .collect(); + + string.push('\n'); + string.push_str(" impl"); + if !generics.is_empty() { + string.push('<'); + for (index, generic) in generics.into_iter().enumerate() { + if index > 0 { + string.push_str(", "); + } + string.push_str(generic); + } + string.push('>'); + } + + string.push(' '); + string.push_str(&trait_.name.0.contents); + if !trait_impl.trait_generics.is_empty() { + string.push('<'); + for (index, generic) in trait_impl.trait_generics.iter().enumerate() { + if index > 0 { + string.push_str(", "); + } + string.push_str(&generic.to_string()); + } + string.push('>'); + } + + string.push_str(" for "); + string.push_str(&trait_impl.typ.to_string()); + + true + } else if let Some(trait_id) = func_meta.trait_id { + let trait_ = args.interner.get_trait(trait_id); + string.push('\n'); + string.push_str(" trait "); + string.push_str(&trait_.name.0.contents); + format_generics(&trait_.generics, &mut string); + + true + } else if let Some(struct_id) = func_meta.struct_id { + let struct_type = args.interner.get_struct(struct_id); + let struct_type = struct_type.borrow(); + if formatted_parent_module { + string.push_str("::"); + } + string.push_str(&struct_type.name.0.contents); + string.push('\n'); + string.push_str(" "); + string.push_str("impl"); + + let impl_generics: Vec<_> = func_meta + .all_generics + .iter() + .take(func_meta.all_generics.len() - func_meta.direct_generics.len()) + .cloned() + .collect(); + format_generics(&impl_generics, &mut string); + + string.push(' '); + string.push_str(&struct_type.name.0.contents); + format_generic_names(&impl_generics, &mut string); + + true + } else { + false + }; + if formatted_parent_module || formatted_parent_type { + string.push('\n'); + } + string.push_str(" "); + + if func_modifiers.visibility != ItemVisibility::Private + && func_meta.trait_id.is_none() + && func_meta.trait_impl.is_none() + { + string.push_str(&func_modifiers.visibility.to_string()); + string.push(' '); + } + if func_modifiers.is_unconstrained { + string.push_str("unconstrained "); + } + if func_modifiers.is_comptime { + string.push_str("comptime "); + } + + let func_name = &func_name_definition_id.name; + + string.push_str("fn "); + string.push_str(func_name); + format_generics(&func_meta.direct_generics, &mut string); + string.push('('); + let parameters = &func_meta.parameters; + for (index, (pattern, typ, visibility)) in parameters.iter().enumerate() { + format_pattern(pattern, args.interner, &mut string); + if !pattern_is_self(pattern, args.interner) { + string.push_str(": "); + if matches!(visibility, Visibility::Public) { + string.push_str("pub "); + } + string.push_str(&format!("{}", typ)); + } + if index != parameters.len() - 1 { + string.push_str(", "); + } + } + + string.push(')'); + + let return_type = func_meta.return_type(); + match return_type { + Type::Unit => (), + _ => { + string.push_str(" -> "); + string.push_str(&format!("{}", return_type)); + } + } + + string.push_str(&go_to_type_links(return_type, args.interner, args.files)); + + let had_doc_comments = + append_doc_comments(args.interner, ReferenceId::Function(id), &mut string); + if !had_doc_comments { + // If this function doesn't have doc comments, but it's a trait impl method, + // use the trait method doc comments. + if let Some(trait_impl_id) = func_meta.trait_impl { + let trait_impl = args.interner.get_trait_implementation(trait_impl_id); + let trait_impl = trait_impl.borrow(); + let trait_ = args.interner.get_trait(trait_impl.trait_id); + if let Some(func_id) = trait_.method_ids.get(func_name) { + append_doc_comments(args.interner, ReferenceId::Function(*func_id), &mut string); + } + } + } + + string +} + +fn get_trait_impl_func_id( + id: FuncId, + args: &ProcessRequestCallbackArgs, + func_meta: &FuncMeta, +) -> Option { + func_meta.trait_id?; + + let index = args.interner.find_location_index(args.location)?; + let expr_id = args.interner.get_expr_id_from_index(index)?; + let Some(TraitImplKind::Normal(trait_impl_id)) = + args.interner.get_selected_impl_for_expression(expr_id) + else { + return None; + }; + + let trait_impl = args.interner.get_trait_implementation(trait_impl_id); + let trait_impl = trait_impl.borrow(); + + let function_name = args.interner.function_name(&id); + let mut trait_impl_methods = trait_impl.methods.iter(); + let func_id = + trait_impl_methods.find(|func_id| args.interner.function_name(func_id) == function_name)?; + Some(*func_id) +} + +fn format_alias(id: TypeAliasId, args: &ProcessRequestCallbackArgs) -> String { + let type_alias = args.interner.get_type_alias(id); + let type_alias = type_alias.borrow(); + + let mut string = String::new(); + format_parent_module(ReferenceId::Alias(id), args, &mut string); + string.push('\n'); + string.push_str(" "); + string.push_str("type "); + string.push_str(&type_alias.name.0.contents); + string.push_str(" = "); + string.push_str(&format!("{}", &type_alias.typ)); + + append_doc_comments(args.interner, ReferenceId::Alias(id), &mut string); + + string +} + +fn format_local(id: DefinitionId, args: &ProcessRequestCallbackArgs) -> String { + let definition_info = args.interner.definition(id); + if let DefinitionKind::Global(global_id) = &definition_info.kind { + return format_global(*global_id, args); + } + + let DefinitionKind::Local(expr_id) = definition_info.kind else { + panic!("Expected a local reference to reference a local definition") + }; + let typ = args.interner.definition_type(id); + + let mut string = String::new(); + string.push_str(" "); + if definition_info.comptime { + string.push_str("comptime "); + } + if expr_id.is_some() { + string.push_str("let "); + } + if definition_info.mutable { + if expr_id.is_none() { + string.push_str("let "); + } + string.push_str("mut "); + } + string.push_str(&definition_info.name); + if !matches!(typ, Type::Error) { + string.push_str(": "); + string.push_str(&format!("{}", typ)); + } + + string.push_str(&go_to_type_links(&typ, args.interner, args.files)); + + string +} + +fn format_generics(generics: &Generics, string: &mut String) { + format_generics_impl( + generics, false, // only show names + string, + ); +} + +fn format_generic_names(generics: &Generics, string: &mut String) { + format_generics_impl( + generics, true, // only show names + string, + ); +} + +fn format_generics_impl(generics: &Generics, only_show_names: bool, string: &mut String) { + if generics.is_empty() { + return; + } + + string.push('<'); + for (index, generic) in generics.iter().enumerate() { + if index > 0 { + string.push_str(", "); + } + + if only_show_names { + string.push_str(&generic.name); + } else { + match generic.kind() { + noirc_frontend::Kind::Any | noirc_frontend::Kind::Normal => { + string.push_str(&generic.name); + } + noirc_frontend::Kind::IntegerOrField | noirc_frontend::Kind::Integer => { + string.push_str("let "); + string.push_str(&generic.name); + string.push_str(": u32"); + } + noirc_frontend::Kind::Numeric(typ) => { + string.push_str("let "); + string.push_str(&generic.name); + string.push_str(": "); + string.push_str(&typ.to_string()); + } + } + } + } + string.push('>'); +} + +fn format_pattern(pattern: &HirPattern, interner: &NodeInterner, string: &mut String) { + match pattern { + HirPattern::Identifier(ident) => { + let definition = interner.definition(ident.id); + string.push_str(&definition.name); + } + HirPattern::Mutable(pattern, _) => { + string.push_str("mut "); + format_pattern(pattern, interner, string); + } + HirPattern::Tuple(..) | HirPattern::Struct(..) => { + string.push('_'); + } + } +} + +fn pattern_is_self(pattern: &HirPattern, interner: &NodeInterner) -> bool { + match pattern { + HirPattern::Identifier(ident) => { + let definition = interner.definition(ident.id); + definition.name == "self" + } + HirPattern::Mutable(pattern, _) => pattern_is_self(pattern, interner), + HirPattern::Tuple(..) | HirPattern::Struct(..) => false, + } +} + +fn format_parent_module( + referenced: ReferenceId, + args: &ProcessRequestCallbackArgs, + string: &mut String, +) -> bool { + let Some(module) = args.interner.reference_module(referenced) else { + return false; + }; + + format_parent_module_from_module_id(module, args, string) +} + +fn format_parent_module_from_module_id( + module: &ModuleId, + args: &ProcessRequestCallbackArgs, + string: &mut String, +) -> bool { + let full_path = + module_full_path(module, args.interner, args.crate_id, &args.crate_name, args.dependencies); + if full_path.is_empty() { + return false; + } + + string.push_str(" "); + string.push_str(&full_path); + true +} + +fn go_to_type_links(typ: &Type, interner: &NodeInterner, files: &FileMap) -> String { + let mut gatherer = TypeLinksGatherer { interner, files, links: Vec::new() }; + gatherer.gather_type_links(typ); + + let links = gatherer.links; + if links.is_empty() { + "".to_string() + } else { + let mut string = String::new(); + string.push_str("\n\n"); + string.push_str("Go to "); + for (index, link) in links.iter().enumerate() { + if index > 0 { + string.push_str(" | "); + } + string.push_str(link); + } + string + } +} + +struct TypeLinksGatherer<'a> { + interner: &'a NodeInterner, + files: &'a FileMap, + links: Vec, +} + +impl<'a> TypeLinksGatherer<'a> { + fn gather_type_links(&mut self, typ: &Type) { + match typ { + Type::Array(typ, _) => self.gather_type_links(typ), + Type::Slice(typ) => self.gather_type_links(typ), + Type::Tuple(types) => { + for typ in types { + self.gather_type_links(typ); + } + } + Type::Struct(struct_type, generics) => { + self.gather_struct_type_links(struct_type); + for generic in generics { + self.gather_type_links(generic); + } + } + Type::Alias(type_alias, generics) => { + self.gather_type_alias_links(type_alias); + for generic in generics { + self.gather_type_links(generic); + } + } + Type::TypeVariable(var) => { + self.gather_type_variable_links(var); + } + Type::TraitAsType(trait_id, _, generics) => { + let some_trait = self.interner.get_trait(*trait_id); + self.gather_trait_links(some_trait); + for generic in &generics.ordered { + self.gather_type_links(generic); + } + for named_type in &generics.named { + self.gather_type_links(&named_type.typ); + } + } + Type::NamedGeneric(var, _) => { + self.gather_type_variable_links(var); + } + Type::Function(args, return_type, env, _) => { + for arg in args { + self.gather_type_links(arg); + } + self.gather_type_links(return_type); + self.gather_type_links(env); + } + Type::MutableReference(typ) => self.gather_type_links(typ), + Type::InfixExpr(lhs, _, rhs) => { + self.gather_type_links(lhs); + self.gather_type_links(rhs); + } + Type::CheckedCast { to, .. } => self.gather_type_links(to), + Type::FieldElement + | Type::Integer(..) + | Type::Bool + | Type::String(_) + | Type::FmtString(_, _) + | Type::Unit + | Type::Forall(_, _) + | Type::Constant(..) + | Type::Quoted(_) + | Type::Error => (), + } + } + + fn gather_struct_type_links(&mut self, struct_type: &Shared) { + let struct_type = struct_type.borrow(); + if let Some(lsp_location) = + to_lsp_location(self.files, struct_type.location.file, struct_type.name.span()) + { + self.push_link(format_link(struct_type.name.to_string(), lsp_location)); + } + } + + fn gather_type_alias_links(&mut self, type_alias: &Shared) { + let type_alias = type_alias.borrow(); + if let Some(lsp_location) = + to_lsp_location(self.files, type_alias.location.file, type_alias.name.span()) + { + self.push_link(format_link(type_alias.name.to_string(), lsp_location)); + } + } + + fn gather_trait_links(&mut self, some_trait: &Trait) { + if let Some(lsp_location) = + to_lsp_location(self.files, some_trait.location.file, some_trait.name.span()) + { + self.push_link(format_link(some_trait.name.to_string(), lsp_location)); + } + } + + fn gather_type_variable_links(&mut self, var: &TypeVariable) { + let var = &*var.borrow(); + match var { + TypeBinding::Bound(typ) => { + self.gather_type_links(typ); + } + TypeBinding::Unbound(..) => (), + } + } + + fn push_link(&mut self, link: String) { + if !self.links.contains(&link) { + self.links.push(link); + } + } +} + +fn format_link(name: String, location: lsp_types::Location) -> String { + format!( + "[{}]({}#L{},{}-{},{})", + name, + location.uri, + location.range.start.line + 1, + location.range.start.character + 1, + location.range.end.line + 1, + location.range.end.character + 1 + ) +} + +fn append_doc_comments(interner: &NodeInterner, id: ReferenceId, string: &mut String) -> bool { + if let Some(doc_comments) = interner.doc_comments(id) { + string.push_str("\n\n---\n\n"); + for comment in doc_comments { + string.push_str(comment); + string.push('\n'); + } + true + } else { + false + } +} + +#[cfg(test)] +mod hover_tests { + use crate::test_utils; + + use super::*; + use lsp_types::{ + Position, TextDocumentIdentifier, TextDocumentPositionParams, Url, WorkDoneProgressParams, + }; + use tokio::test; + + async fn assert_hover(directory: &str, file: &str, position: Position, expected_text: &str) { + let hover_text = get_hover_text(directory, file, position).await; + assert_eq!(hover_text, expected_text); + } + + async fn get_hover_text(directory: &str, file: &str, position: Position) -> String { + let (mut state, noir_text_document) = test_utils::init_lsp_server(directory).await; + + // noir_text_document is always `src/main.nr` in the workspace directory, so let's go to the workspace dir + let noir_text_document = noir_text_document.to_file_path().unwrap(); + let workspace_dir = noir_text_document.parent().unwrap().parent().unwrap(); + + let file_uri = Url::from_file_path(workspace_dir.join(file)).unwrap(); + + let hover = on_hover_request( + &mut state, + HoverParams { + text_document_position_params: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: file_uri }, + position, + }, + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + }, + ) + .await + .expect("Could not execute hover") + .unwrap(); + + let HoverContents::Markup(markup) = hover.contents else { + panic!("Expected hover contents to be Markup"); + }; + + markup.value + } + + #[test] + async fn hover_on_module() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 6, character: 9 }, + r#" one + mod subone"#, + ) + .await; + } + + #[test] + async fn hover_on_struct() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 9, character: 20 }, + r#" one::subone + struct SubOneStruct { + some_field: i32, + some_other_field: Field, + }"#, + ) + .await; + } + + #[test] + async fn hover_on_generic_struct() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 46, character: 17 }, + r#" one::subone + struct GenericStruct { + }"#, + ) + .await; + } + + #[test] + async fn hover_on_struct_member() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 9, character: 35 }, + r#" one::subone::SubOneStruct + some_field: i32"#, + ) + .await; + } + + #[test] + async fn hover_on_trait() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 12, character: 17 }, + r#" one::subone + trait SomeTrait"#, + ) + .await; + } + + #[test] + async fn hover_on_global() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 15, character: 25 }, + r#" one::subone + global some_global: Field = 2"#, + ) + .await; + } + + #[test] + async fn hover_on_function() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 3, character: 4 }, + r#" one + pub fn function_one()"#, + ) + .await; + } + + #[test] + async fn hover_on_local_function() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 2, character: 7 }, + r#" two + pub fn function_two()"#, + ) + .await; + } + + #[test] + async fn hover_on_struct_method() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 20, character: 6 }, + r#" one::subone::SubOneStruct + impl SubOneStruct + fn foo(self, x: i32, y: i32) -> Field"#, + ) + .await; + } + + #[test] + async fn hover_on_local_var() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 25, character: 12 }, + " let regular_var: Field", + ) + .await; + } + + #[test] + async fn hover_on_local_mut_var() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 27, character: 4 }, + " let mut mutable_var: Field", + ) + .await; + } + + #[test] + async fn hover_on_local_var_whose_type_you_can_navigate_to() { + let workspace_on_src_lib_path = std::env::current_dir() + .unwrap() + .join("test_programs/workspace/one/src/lib.nr") + .canonicalize() + .expect("Could not resolve root path"); + let workspace_on_src_lib_path = workspace_on_src_lib_path.to_string_lossy(); + + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 51, character: 8 }, + &format!(" let x: BoundedVec\n\nGo to [SubOneStruct](file://{}#L4,12-4,24)", workspace_on_src_lib_path), + ) + .await; + } + + #[test] + async fn hover_on_parameter() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 31, character: 12 }, + " some_param: i32", + ) + .await; + } + + #[test] + async fn hover_on_alias() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 34, character: 17 }, + r#" one::subone + type SomeAlias = i32"#, + ) + .await; + } + + #[test] + async fn hover_on_trait_on_call() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 39, character: 17 }, + r#" std::default + trait Default"#, + ) + .await; + } + + #[test] + async fn hover_on_std_module_in_use() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 36, character: 9 }, + r#" std + mod default"#, + ) + .await; + } + + #[test] + async fn hover_on_crate_module_in_call() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 15, character: 17 }, + r#" one + mod subone"#, + ) + .await; + } + + #[test] + async fn hover_on_module_without_crate_or_std_prefix() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 42, character: 4 }, + r#" two + mod other"#, + ) + .await; + } + + #[test] + async fn hover_on_module_with_crate_prefix() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 43, character: 11 }, + r#" two + mod other"#, + ) + .await; + } + + #[test] + async fn hover_on_module_on_struct_constructor() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 19, character: 12 }, + r#" one + mod subone"#, + ) + .await; + } + + #[test] + async fn hover_on_type_inside_generic_arguments() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 51, character: 30 }, + r#" one::subone + struct SubOneStruct { + some_field: i32, + some_other_field: Field, + }"#, + ) + .await; + } + + #[test] + async fn hover_on_crate_segment() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 0, character: 5 }, + " crate one", + ) + .await; + } + + #[test] + async fn hover_on_attribute_function() { + assert_hover( + "workspace", + "two/src/lib.nr", + Position { line: 54, character: 2 }, + " two\n comptime fn attr(_: FunctionDefinition) -> Quoted", + ) + .await; + } + + #[test] + async fn hover_on_generic_struct_function() { + let hover_text = + get_hover_text("workspace", "two/src/lib.nr", Position { line: 70, character: 11 }) + .await; + assert!(hover_text.starts_with( + " two::Foo + impl Foo + fn new() -> Foo" + )); + } + + #[test] + async fn hover_on_trait_impl_function_call() { + let hover_text = + get_hover_text("workspace", "two/src/lib.nr", Position { line: 83, character: 16 }) + .await; + assert!(hover_text.starts_with( + " two + impl Bar for Foo + fn bar_stuff(self)" + )); + } + + #[test] + async fn hover_on_trait_impl_method_uses_docs_from_trait_method() { + let hover_text = + get_hover_text("workspace", "two/src/lib.nr", Position { line: 92, character: 8 }) + .await; + assert!(hover_text.contains("Some docs")); + } +} diff --git a/tooling/lsp/src/requests/inlay_hint.rs b/tooling/lsp/src/requests/inlay_hint.rs new file mode 100644 index 00000000000..c6415acb545 --- /dev/null +++ b/tooling/lsp/src/requests/inlay_hint.rs @@ -0,0 +1,958 @@ +use std::future::{self, Future}; + +use async_lsp::ResponseError; +use fm::{FileId, FileMap, PathString}; +use lsp_types::{ + InlayHint, InlayHintKind, InlayHintLabel, InlayHintLabelPart, InlayHintParams, Position, Range, + TextDocumentPositionParams, TextEdit, +}; +use noirc_errors::{Location, Span}; +use noirc_frontend::{ + self, + ast::{ + CallExpression, Expression, ExpressionKind, ForLoopStatement, Ident, Lambda, LetStatement, + MethodCallExpression, NoirFunction, NoirTraitImpl, Pattern, Statement, TypeImpl, + UnresolvedTypeData, Visitor, + }, + hir_def::stmt::HirPattern, + node_interner::{NodeInterner, ReferenceId}, + parser::{Item, ParsedSubModule}, + Kind, Type, TypeBinding, TypeVariable, +}; + +use crate::{utils, LspState}; + +use super::{process_request, to_lsp_location, InlayHintsOptions}; + +pub(crate) fn on_inlay_hint_request( + state: &mut LspState, + params: InlayHintParams, +) -> impl Future>, ResponseError>> { + let text_document_position_params = TextDocumentPositionParams { + text_document: params.text_document.clone(), + position: Position { line: 0, character: 0 }, + }; + + let options = state.options.inlay_hints; + + let result = process_request(state, text_document_position_params, |args| { + let path = PathString::from_path(params.text_document.uri.to_file_path().unwrap()); + args.files.get_file_id(&path).map(|file_id| { + let file = args.files.get_file(file_id).unwrap(); + let source = file.source(); + let (parsed_moduled, _errors) = noirc_frontend::parse_program(source); + + let span = utils::range_to_byte_span(args.files, file_id, ¶ms.range) + .map(|range| Span::from(range.start as u32..range.end as u32)); + + let mut collector = + InlayHintCollector::new(args.files, file_id, args.interner, span, options); + parsed_moduled.accept(&mut collector); + collector.inlay_hints + }) + }); + future::ready(result) +} + +pub(crate) struct InlayHintCollector<'a> { + files: &'a FileMap, + file_id: FileId, + interner: &'a NodeInterner, + span: Option, + options: InlayHintsOptions, + inlay_hints: Vec, +} + +impl<'a> InlayHintCollector<'a> { + fn new( + files: &'a FileMap, + file_id: FileId, + interner: &'a NodeInterner, + span: Option, + options: InlayHintsOptions, + ) -> InlayHintCollector<'a> { + InlayHintCollector { files, file_id, interner, span, options, inlay_hints: Vec::new() } + } + + fn collect_in_ident(&mut self, ident: &Ident, editable: bool) { + if !self.options.type_hints.enabled { + return; + } + + let span = ident.span(); + let location = Location::new(ident.span(), self.file_id); + if let Some(lsp_location) = to_lsp_location(self.files, self.file_id, span) { + if let Some(referenced) = self.interner.find_referenced(location) { + match referenced { + ReferenceId::Global(global_id) => { + let global_info = self.interner.get_global(global_id); + let definition_id = global_info.definition_id; + let typ = self.interner.definition_type(definition_id); + self.push_type_hint(lsp_location, &typ, editable); + } + ReferenceId::Local(definition_id) => { + let typ = self.interner.definition_type(definition_id); + self.push_type_hint(lsp_location, &typ, editable); + } + ReferenceId::StructMember(struct_id, field_index) => { + let struct_type = self.interner.get_struct(struct_id); + let struct_type = struct_type.borrow(); + let field = struct_type.field_at(field_index); + self.push_type_hint(lsp_location, &field.typ, false); + } + ReferenceId::Module(_) + | ReferenceId::Struct(_) + | ReferenceId::Trait(_) + | ReferenceId::Function(_) + | ReferenceId::Alias(_) + | ReferenceId::Reference(..) => (), + } + } + } + } + + fn push_type_hint(&mut self, location: lsp_types::Location, typ: &Type, editable: bool) { + let position = location.range.end; + + let mut parts = Vec::new(); + parts.push(string_part(": ")); + push_type_parts(typ, &mut parts, self.files); + + self.inlay_hints.push(InlayHint { + position, + label: InlayHintLabel::LabelParts(parts), + kind: Some(InlayHintKind::TYPE), + text_edits: if editable { + Some(vec![TextEdit { + range: Range { start: location.range.end, end: location.range.end }, + new_text: format!(": {}", typ), + }]) + } else { + None + }, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }); + } + + fn collect_call_parameter_names( + &mut self, + function_name: Option, + at: Span, + arguments: &[Expression], + ) { + if !self.options.parameter_hints.enabled { + return; + } + + // The `at` span might be the span of a path like `Foo::bar`. + // In order to find the function behind it, we use a span that is just the last char. + let at = Span::single_char(at.end() - 1); + + let referenced = self.interner.find_referenced(Location::new(at, self.file_id)); + if let Some(ReferenceId::Function(func_id)) = referenced { + let func_meta = self.interner.function_meta(&func_id); + + let mut parameters = func_meta.parameters.iter().peekable(); + let mut parameters_count = func_meta.parameters.len(); + + // Skip `self` parameter + if let Some((pattern, _, _)) = parameters.peek() { + if self.is_self_parameter(pattern) { + parameters.next(); + parameters_count -= 1; + } + } + + for (call_argument, (pattern, _, _)) in arguments.iter().zip(parameters) { + let Some(lsp_location) = + to_lsp_location(self.files, self.file_id, call_argument.span) + else { + continue; + }; + + let Some(parameter_name) = self.get_pattern_name(pattern) else { + continue; + }; + + if parameter_name.starts_with('_') { + continue; + } + + if parameters_count == 1 { + if parameter_name.len() == 1 + || parameter_name == "other" + || parameter_name == "value" + { + continue; + } + + if let Some(function_name) = &function_name { + if function_name.ends_with(¶meter_name) { + continue; + } + } + } + + if let Some(call_argument_name) = get_expression_name(call_argument) { + if parameter_name == call_argument_name + || call_argument_name.ends_with(¶meter_name) + { + continue; + } + } + + self.push_parameter_hint(lsp_location.range.start, ¶meter_name); + } + } + } + + fn get_pattern_name(&self, pattern: &HirPattern) -> Option { + match pattern { + HirPattern::Identifier(ident) => { + let definition = self.interner.definition(ident.id); + Some(definition.name.clone()) + } + HirPattern::Mutable(pattern, _location) => self.get_pattern_name(pattern), + HirPattern::Tuple(..) | HirPattern::Struct(..) => None, + } + } + + fn push_parameter_hint(&mut self, position: Position, str: &str) { + self.push_text_hint(position, format!("{}: ", str)); + } + + fn push_text_hint(&mut self, position: Position, str: String) { + self.inlay_hints.push(InlayHint { + position, + label: InlayHintLabel::String(str), + kind: Some(InlayHintKind::PARAMETER), + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }); + } + + fn is_self_parameter(&self, pattern: &HirPattern) -> bool { + match pattern { + HirPattern::Identifier(ident) => { + let definition_info = self.interner.definition(ident.id); + definition_info.name == "self" + } + HirPattern::Mutable(pattern, _location) => self.is_self_parameter(pattern), + HirPattern::Tuple(..) | HirPattern::Struct(..) => false, + } + } + + fn intersects_span(&self, other_span: Span) -> bool { + self.span.map_or(true, |span| span.intersects(&other_span)) + } + + fn show_closing_brace_hint(&mut self, span: Span, f: F) + where + F: FnOnce() -> String, + { + if self.options.closing_brace_hints.enabled { + if let Some(lsp_location) = to_lsp_location(self.files, self.file_id, span) { + let lines = lsp_location.range.end.line - lsp_location.range.start.line + 1; + if lines >= self.options.closing_brace_hints.min_lines { + self.push_text_hint(lsp_location.range.end, f()); + } + } + } + } +} + +impl<'a> Visitor for InlayHintCollector<'a> { + fn visit_item(&mut self, item: &Item) -> bool { + self.intersects_span(item.span) + } + + fn visit_noir_trait_impl(&mut self, noir_trait_impl: &NoirTraitImpl, span: Span) -> bool { + self.show_closing_brace_hint(span, || { + format!(" impl {} for {}", noir_trait_impl.trait_name, noir_trait_impl.object_type) + }); + + true + } + + fn visit_type_impl(&mut self, type_impl: &TypeImpl, span: Span) -> bool { + self.show_closing_brace_hint(span, || format!(" impl {}", type_impl.object_type)); + + true + } + + fn visit_parsed_submodule(&mut self, parsed_submodule: &ParsedSubModule, span: Span) -> bool { + self.show_closing_brace_hint(span, || { + if parsed_submodule.is_contract { + format!(" contract {}", parsed_submodule.name) + } else { + format!(" mod {}", parsed_submodule.name) + } + }); + + true + } + + fn visit_noir_function(&mut self, noir_function: &NoirFunction, span: Span) -> bool { + self.show_closing_brace_hint(span, || format!(" fn {}", noir_function.def.name)); + + true + } + + fn visit_statement(&mut self, statement: &Statement) -> bool { + self.intersects_span(statement.span) + } + + fn visit_let_statement(&mut self, let_statement: &LetStatement) -> bool { + // Only show inlay hints for let variables that don't have an explicit type annotation + if let UnresolvedTypeData::Unspecified = let_statement.r#type.typ { + let_statement.pattern.accept(self); + }; + + let_statement.expression.accept(self); + + false + } + + fn visit_for_loop_statement(&mut self, for_loop_statement: &ForLoopStatement) -> bool { + self.collect_in_ident(&for_loop_statement.identifier, false); + true + } + + fn visit_expression(&mut self, expression: &Expression) -> bool { + self.intersects_span(expression.span) + } + + fn visit_call_expression(&mut self, call_expression: &CallExpression, _: Span) -> bool { + self.collect_call_parameter_names( + get_expression_name(&call_expression.func), + call_expression.func.span, + &call_expression.arguments, + ); + + true + } + + fn visit_method_call_expression( + &mut self, + method_call_expression: &MethodCallExpression, + _: Span, + ) -> bool { + self.collect_call_parameter_names( + Some(method_call_expression.method_name.to_string()), + method_call_expression.method_name.span(), + &method_call_expression.arguments, + ); + + true + } + + fn visit_lambda(&mut self, lambda: &Lambda, _: Span) -> bool { + for (pattern, typ) in &lambda.parameters { + if matches!(typ.typ, UnresolvedTypeData::Unspecified) { + pattern.accept(self); + } + } + + lambda.body.accept(self); + + false + } + + fn visit_pattern(&mut self, _: &Pattern) -> bool { + self.options.type_hints.enabled + } + + fn visit_identifier_pattern(&mut self, ident: &Ident) { + self.collect_in_ident(ident, true); + } +} + +fn string_part(str: impl Into) -> InlayHintLabelPart { + InlayHintLabelPart { value: str.into(), location: None, tooltip: None, command: None } +} + +fn text_part_with_location(str: String, location: Location, files: &FileMap) -> InlayHintLabelPart { + InlayHintLabelPart { + value: str, + location: to_lsp_location(files, location.file, location.span), + tooltip: None, + command: None, + } +} + +fn push_type_parts(typ: &Type, parts: &mut Vec, files: &FileMap) { + match typ { + Type::Array(size, typ) => { + parts.push(string_part("[")); + push_type_parts(typ, parts, files); + parts.push(string_part("; ")); + push_type_parts(size, parts, files); + parts.push(string_part("]")); + } + Type::Slice(typ) => { + parts.push(string_part("[")); + push_type_parts(typ, parts, files); + parts.push(string_part("]")); + } + Type::Tuple(types) => { + parts.push(string_part("(")); + for (index, typ) in types.iter().enumerate() { + push_type_parts(typ, parts, files); + if index != types.len() - 1 { + parts.push(string_part(", ")); + } + } + parts.push(string_part(")")); + } + Type::Struct(struct_type, generics) => { + let struct_type = struct_type.borrow(); + let location = Location::new(struct_type.name.span(), struct_type.location.file); + parts.push(text_part_with_location(struct_type.name.to_string(), location, files)); + if !generics.is_empty() { + parts.push(string_part("<")); + for (index, generic) in generics.iter().enumerate() { + push_type_parts(generic, parts, files); + if index != generics.len() - 1 { + parts.push(string_part(", ")); + } + } + parts.push(string_part(">")); + } + } + Type::Alias(type_alias, generics) => { + let type_alias = type_alias.borrow(); + let location = Location::new(type_alias.name.span(), type_alias.location.file); + parts.push(text_part_with_location(type_alias.name.to_string(), location, files)); + if !generics.is_empty() { + parts.push(string_part("<")); + for (index, generic) in generics.iter().enumerate() { + push_type_parts(generic, parts, files); + if index != generics.len() - 1 { + parts.push(string_part(", ")); + } + } + parts.push(string_part(">")); + } + } + Type::Function(args, return_type, _env, unconstrained) => { + if *unconstrained { + parts.push(string_part("unconstrained ")); + } + + parts.push(string_part("fn(")); + for (index, arg) in args.iter().enumerate() { + push_type_parts(arg, parts, files); + if index != args.len() - 1 { + parts.push(string_part(", ")); + } + } + parts.push(string_part(") -> ")); + push_type_parts(return_type, parts, files); + } + Type::MutableReference(typ) => { + parts.push(string_part("&mut ")); + push_type_parts(typ, parts, files); + } + Type::TypeVariable(binding) => { + if let TypeBinding::Unbound(_, kind) = &*binding.borrow() { + match kind { + Kind::Any | Kind::Normal => push_type_variable_parts(binding, parts, files), + Kind::Integer => push_type_parts(&Type::default_int_type(), parts, files), + Kind::IntegerOrField => parts.push(string_part("Field")), + Kind::Numeric(ref typ) => push_type_parts(typ, parts, files), + } + } else { + push_type_variable_parts(binding, parts, files); + } + } + Type::CheckedCast { to, .. } => push_type_parts(to, parts, files), + + Type::FieldElement + | Type::Integer(..) + | Type::Bool + | Type::String(..) + | Type::FmtString(..) + | Type::Unit + | Type::TraitAsType(..) + | Type::NamedGeneric(..) + | Type::Forall(..) + | Type::Constant(..) + | Type::InfixExpr(..) + | Type::Quoted(..) + | Type::Error => { + parts.push(string_part(typ.to_string())); + } + } +} + +fn push_type_variable_parts( + var: &TypeVariable, + parts: &mut Vec, + files: &FileMap, +) { + let var = &*var.borrow(); + match var { + TypeBinding::Bound(typ) => { + push_type_parts(typ, parts, files); + } + TypeBinding::Unbound(..) => { + parts.push(string_part(var.to_string())); + } + } +} + +fn get_expression_name(expression: &Expression) -> Option { + match &expression.kind { + ExpressionKind::Variable(path) => Some(path.last_name().to_string()), + ExpressionKind::Prefix(prefix) => get_expression_name(&prefix.rhs), + ExpressionKind::MemberAccess(member_access) => Some(member_access.rhs.to_string()), + ExpressionKind::Call(call) => get_expression_name(&call.func), + ExpressionKind::MethodCall(method_call) => Some(method_call.method_name.to_string()), + ExpressionKind::Cast(cast) => get_expression_name(&cast.lhs), + ExpressionKind::Parenthesized(expr) => get_expression_name(expr), + ExpressionKind::AsTraitPath(path) => Some(path.impl_item.to_string()), + ExpressionKind::TypePath(path) => Some(path.item.to_string()), + ExpressionKind::Constructor(..) + | ExpressionKind::Infix(..) + | ExpressionKind::Index(..) + | ExpressionKind::Block(..) + | ExpressionKind::If(..) + | ExpressionKind::Lambda(..) + | ExpressionKind::Tuple(..) + | ExpressionKind::Quote(..) + | ExpressionKind::Unquote(..) + | ExpressionKind::Comptime(..) + | ExpressionKind::Resolved(..) + | ExpressionKind::Interned(..) + | ExpressionKind::InternedStatement(..) + | ExpressionKind::Literal(..) + | ExpressionKind::Unsafe(..) + | ExpressionKind::Error => None, + } +} + +#[cfg(test)] +mod inlay_hints_tests { + use crate::{ + requests::{ClosingBraceHintsOptions, ParameterHintsOptions, TypeHintsOptions}, + test_utils, + }; + + use super::*; + use lsp_types::{Range, TextDocumentIdentifier, WorkDoneProgressParams}; + use tokio::test; + + async fn get_inlay_hints( + start_line: u32, + end_line: u32, + options: InlayHintsOptions, + ) -> Vec { + let (mut state, noir_text_document) = test_utils::init_lsp_server("inlay_hints").await; + state.options.inlay_hints = options; + + on_inlay_hint_request( + &mut state, + InlayHintParams { + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + text_document: TextDocumentIdentifier { uri: noir_text_document }, + range: Range { + start: Position { line: start_line, character: 0 }, + end: Position { line: end_line, character: 0 }, + }, + }, + ) + .await + .expect("Could not execute on_inlay_hint_request") + .unwrap() + } + + fn no_hints() -> InlayHintsOptions { + InlayHintsOptions { + type_hints: TypeHintsOptions { enabled: false }, + parameter_hints: ParameterHintsOptions { enabled: false }, + closing_brace_hints: ClosingBraceHintsOptions { enabled: false, min_lines: 25 }, + } + } + + fn type_hints() -> InlayHintsOptions { + InlayHintsOptions { + type_hints: TypeHintsOptions { enabled: true }, + parameter_hints: ParameterHintsOptions { enabled: false }, + closing_brace_hints: ClosingBraceHintsOptions { enabled: false, min_lines: 25 }, + } + } + + fn parameter_hints() -> InlayHintsOptions { + InlayHintsOptions { + type_hints: TypeHintsOptions { enabled: false }, + parameter_hints: ParameterHintsOptions { enabled: true }, + closing_brace_hints: ClosingBraceHintsOptions { enabled: false, min_lines: 25 }, + } + } + + fn closing_braces_hints(min_lines: u32) -> InlayHintsOptions { + InlayHintsOptions { + type_hints: TypeHintsOptions { enabled: false }, + parameter_hints: ParameterHintsOptions { enabled: false }, + closing_brace_hints: ClosingBraceHintsOptions { enabled: true, min_lines }, + } + } + + #[test] + async fn test_do_not_collect_type_hints_if_disabled() { + let inlay_hints = get_inlay_hints(0, 3, no_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_type_inlay_hints_without_location() { + let inlay_hints = get_inlay_hints(0, 3, type_hints()).await; + assert_eq!(inlay_hints.len(), 1); + + let position = Position { line: 1, character: 11 }; + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, position); + + if let InlayHintLabel::LabelParts(labels) = &inlay_hint.label { + assert_eq!(labels.len(), 2); + assert_eq!(labels[0].value, ": "); + assert_eq!(labels[0].location, None); + assert_eq!(labels[1].value, "Field"); + + // Field can't be reached (there's no source code for it) + assert_eq!(labels[1].location, None); + } else { + panic!("Expected InlayHintLabel::LabelParts, got {:?}", inlay_hint.label); + } + + assert_eq!( + inlay_hint.text_edits, + Some(vec![TextEdit { + range: Range { start: position, end: position }, + new_text: ": Field".to_string(), + }]) + ); + } + + #[test] + async fn test_type_inlay_hints_with_location() { + let inlay_hints = get_inlay_hints(12, 15, type_hints()).await; + assert_eq!(inlay_hints.len(), 1); + + let position = Position { line: 13, character: 11 }; + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, position); + + if let InlayHintLabel::LabelParts(labels) = &inlay_hint.label { + assert_eq!(labels.len(), 2); + assert_eq!(labels[0].value, ": "); + assert_eq!(labels[0].location, None); + assert_eq!(labels[1].value, "Foo"); + + // Check that it points to "Foo" in `struct Foo` + let location = labels[1].location.clone().expect("Expected a location"); + assert_eq!( + location.range, + Range { + start: Position { line: 4, character: 7 }, + end: Position { line: 4, character: 10 } + } + ); + } else { + panic!("Expected InlayHintLabel::LabelParts, got {:?}", inlay_hint.label); + } + + assert_eq!( + inlay_hint.text_edits, + Some(vec![TextEdit { + range: Range { start: position, end: position }, + new_text: ": Foo".to_string(), + }]) + ); + } + + #[test] + async fn test_type_inlay_hints_in_struct_member_pattern() { + let inlay_hints = get_inlay_hints(94, 96, type_hints()).await; + assert_eq!(inlay_hints.len(), 1); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 95, character: 24 }); + + if let InlayHintLabel::LabelParts(labels) = &inlay_hint.label { + assert_eq!(labels.len(), 2); + assert_eq!(labels[0].value, ": "); + assert_eq!(labels[0].location, None); + assert_eq!(labels[1].value, "i32"); + } else { + panic!("Expected InlayHintLabel::LabelParts, got {:?}", inlay_hint.label); + } + + assert_eq!(inlay_hint.text_edits, None); + } + + #[test] + async fn test_type_inlay_hints_in_for() { + let inlay_hints = get_inlay_hints(16, 18, type_hints()).await; + assert_eq!(inlay_hints.len(), 1); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 17, character: 9 }); + + if let InlayHintLabel::LabelParts(labels) = &inlay_hint.label { + assert_eq!(labels.len(), 2); + assert_eq!(labels[0].value, ": "); + assert_eq!(labels[0].location, None); + assert_eq!(labels[1].value, "u32"); + } else { + panic!("Expected InlayHintLabel::LabelParts, got {:?}", inlay_hint.label); + } + + assert_eq!(inlay_hint.text_edits, None); + } + + #[test] + async fn test_type_inlay_hints_in_global() { + let inlay_hints = get_inlay_hints(19, 21, type_hints()).await; + assert_eq!(inlay_hints.len(), 1); + + let position = Position { line: 20, character: 10 }; + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, position); + + if let InlayHintLabel::LabelParts(labels) = &inlay_hint.label { + assert_eq!(labels.len(), 2); + assert_eq!(labels[0].value, ": "); + assert_eq!(labels[0].location, None); + assert_eq!(labels[1].value, "Field"); + } else { + panic!("Expected InlayHintLabel::LabelParts, got {:?}", inlay_hint.label); + } + + assert_eq!( + inlay_hint.text_edits, + Some(vec![TextEdit { + range: Range { start: position, end: position }, + new_text: ": Field".to_string(), + }]) + ); + } + + #[test] + async fn test_type_inlay_hints_in_lambda() { + let inlay_hints = get_inlay_hints(102, 105, type_hints()).await; + assert_eq!(inlay_hints.len(), 1); + + let position = Position { line: 104, character: 35 }; + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, position); + + if let InlayHintLabel::LabelParts(labels) = &inlay_hint.label { + assert_eq!(labels.len(), 2); + assert_eq!(labels[0].value, ": "); + assert_eq!(labels[0].location, None); + assert_eq!(labels[1].value, "i32"); + } else { + panic!("Expected InlayHintLabel::LabelParts, got {:?}", inlay_hint.label); + } + + assert_eq!( + inlay_hint.text_edits, + Some(vec![TextEdit { + range: Range { start: position, end: position }, + new_text: ": i32".to_string(), + }]) + ); + } + + #[test] + async fn test_do_not_panic_when_given_line_is_too_big() { + let inlay_hints = get_inlay_hints(0, 100000, type_hints()).await; + assert!(!inlay_hints.is_empty()); + } + + #[test] + async fn test_do_not_collect_parameter_inlay_hints_if_disabled() { + let inlay_hints = get_inlay_hints(24, 26, no_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_collect_parameter_inlay_hints_in_function_call() { + let inlay_hints = get_inlay_hints(24, 26, parameter_hints()).await; + assert_eq!(inlay_hints.len(), 2); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 25, character: 12 }); + assert_eq!(inlay_hint.text_edits, None); + if let InlayHintLabel::String(label) = &inlay_hint.label { + assert_eq!(label, "one: "); + } else { + panic!("Expected InlayHintLabel::String, got {:?}", inlay_hint.label); + } + + let inlay_hint = &inlay_hints[1]; + assert_eq!(inlay_hint.position, Position { line: 25, character: 15 }); + assert_eq!(inlay_hint.text_edits, None); + if let InlayHintLabel::String(label) = &inlay_hint.label { + assert_eq!(label, "two: "); + } else { + panic!("Expected InlayHintLabel::String, got {:?}", inlay_hint.label); + } + } + + #[test] + async fn test_collect_parameter_inlay_hints_in_method_call() { + let inlay_hints = get_inlay_hints(36, 39, parameter_hints()).await; + assert_eq!(inlay_hints.len(), 1); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 38, character: 18 }); + assert_eq!(inlay_hint.text_edits, None); + if let InlayHintLabel::String(label) = &inlay_hint.label { + assert_eq!(label, "one: "); + } else { + panic!("Expected InlayHintLabel::String, got {:?}", inlay_hint.label); + } + } + + #[test] + async fn test_do_not_show_parameter_inlay_hints_if_name_matches_var_name() { + let inlay_hints = get_inlay_hints(41, 45, parameter_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_do_not_show_parameter_inlay_hints_if_name_matches_member_name() { + let inlay_hints = get_inlay_hints(48, 52, parameter_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_do_not_show_parameter_inlay_hints_if_name_matches_call_name() { + let inlay_hints = get_inlay_hints(57, 60, parameter_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_do_not_show_parameter_inlay_hints_if_single_param_name_is_suffix_of_function_name( + ) { + let inlay_hints = get_inlay_hints(64, 67, parameter_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_do_not_show_parameter_inlay_hints_if_param_name_starts_with_underscore() { + let inlay_hints = get_inlay_hints(71, 73, parameter_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_do_not_show_parameter_inlay_hints_if_single_argument_with_single_letter() { + let inlay_hints = get_inlay_hints(77, 79, parameter_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_do_not_show_parameter_inlay_hints_if_param_name_is_suffix_of_arg_name() { + let inlay_hints = get_inlay_hints(89, 92, parameter_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_does_not_show_closing_brace_inlay_hints_if_disabled() { + let inlay_hints = get_inlay_hints(41, 46, no_hints()).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_does_not_show_closing_brace_inlay_hints_if_enabled_but_not_lines() { + let inlay_hints = get_inlay_hints(41, 46, closing_braces_hints(6)).await; + assert!(inlay_hints.is_empty()); + } + + #[test] + async fn test_shows_closing_brace_inlay_hints_for_a_function() { + let inlay_hints = get_inlay_hints(41, 46, closing_braces_hints(5)).await; + assert_eq!(inlay_hints.len(), 1); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 45, character: 1 }); + assert_eq!(inlay_hint.text_edits, None); + if let InlayHintLabel::String(label) = &inlay_hint.label { + assert_eq!(label, " fn call_where_name_matches"); + } else { + panic!("Expected InlayHintLabel::String, got {:?}", inlay_hint.label); + } + } + + #[test] + async fn test_shows_closing_brace_inlay_hints_for_impl() { + let inlay_hints = get_inlay_hints(32, 34, closing_braces_hints(2)).await; + assert_eq!(inlay_hints.len(), 1); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 34, character: 1 }); + assert_eq!(inlay_hint.text_edits, None); + if let InlayHintLabel::String(label) = &inlay_hint.label { + assert_eq!(label, " impl SomeStruct"); + } else { + panic!("Expected InlayHintLabel::String, got {:?}", inlay_hint.label); + } + } + + #[test] + async fn test_shows_closing_brace_inlay_hints_for_trait_impl() { + let inlay_hints = get_inlay_hints(111, 113, closing_braces_hints(2)).await; + assert_eq!(inlay_hints.len(), 1); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 113, character: 1 }); + assert_eq!(inlay_hint.text_edits, None); + if let InlayHintLabel::String(label) = &inlay_hint.label { + assert_eq!(label, " impl SomeTrait for SomeStruct"); + } else { + panic!("Expected InlayHintLabel::String, got {:?}", inlay_hint.label); + } + } + + #[test] + async fn test_shows_closing_brace_inlay_hints_for_module() { + let inlay_hints = get_inlay_hints(115, 117, closing_braces_hints(2)).await; + assert_eq!(inlay_hints.len(), 1); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 117, character: 1 }); + assert_eq!(inlay_hint.text_edits, None); + if let InlayHintLabel::String(label) = &inlay_hint.label { + assert_eq!(label, " mod some_module"); + } else { + panic!("Expected InlayHintLabel::String, got {:?}", inlay_hint.label); + } + } + + #[test] + async fn test_shows_closing_brace_inlay_hints_for_contract() { + let inlay_hints = get_inlay_hints(119, 121, closing_braces_hints(2)).await; + assert_eq!(inlay_hints.len(), 1); + + let inlay_hint = &inlay_hints[0]; + assert_eq!(inlay_hint.position, Position { line: 121, character: 1 }); + assert_eq!(inlay_hint.text_edits, None); + if let InlayHintLabel::String(label) = &inlay_hint.label { + assert_eq!(label, " contract some_contract"); + } else { + panic!("Expected InlayHintLabel::String, got {:?}", inlay_hint.label); + } + } +} diff --git a/tooling/lsp/src/requests/mod.rs b/tooling/lsp/src/requests/mod.rs new file mode 100644 index 00000000000..d81108c2ec5 --- /dev/null +++ b/tooling/lsp/src/requests/mod.rs @@ -0,0 +1,674 @@ +use std::collections::BTreeMap; +use std::path::PathBuf; +use std::{collections::HashMap, future::Future}; + +use crate::{insert_all_files_for_workspace_into_file_manager, parse_diff, PackageCacheData}; +use crate::{ + resolve_workspace_for_source_path, + types::{CodeLensOptions, InitializeParams}, +}; +use async_lsp::{ErrorCode, ResponseError}; +use fm::{codespan_files::Error, FileMap, PathString}; +use lsp_types::{ + CodeActionKind, DeclarationCapability, Location, Position, TextDocumentPositionParams, + TextDocumentSyncCapability, TextDocumentSyncKind, TypeDefinitionProviderCapability, Url, + WorkDoneProgressOptions, +}; +use nargo_fmt::Config; + +use noirc_frontend::graph::CrateId; +use noirc_frontend::hir::def_map::CrateDefMap; +use noirc_frontend::parser::ParserError; +use noirc_frontend::usage_tracker::UsageTracker; +use noirc_frontend::{graph::Dependency, node_interner::NodeInterner}; +use serde::{Deserialize, Serialize}; + +use crate::{ + types::{InitializeResult, NargoCapability, NargoTestsOptions, ServerCapabilities}, + LspState, +}; + +// Handlers +// The handlers for `request` are not `async` because it compiles down to lifetimes that can't be added to +// the router. To return a future that fits the trait, it is easiest wrap your implementations in an `async {}` +// block but you can also use `std::future::ready`. +// +// Additionally, the handlers for `notification` aren't async at all. +// +// They are not attached to the `NargoLspService` struct so they can be unit tested with only `LspState` +// and params passed in. + +mod code_action; +mod code_lens_request; +mod completion; +mod document_symbol; +mod goto_declaration; +mod goto_definition; +mod hover; +mod inlay_hint; +mod references; +mod rename; +mod signature_help; +mod test_run; +mod tests; + +pub(crate) use { + code_action::on_code_action_request, code_lens_request::collect_lenses_for_package, + code_lens_request::on_code_lens_request, completion::on_completion_request, + document_symbol::on_document_symbol_request, goto_declaration::on_goto_declaration_request, + goto_definition::on_goto_definition_request, goto_definition::on_goto_type_definition_request, + hover::on_hover_request, inlay_hint::on_inlay_hint_request, references::on_references_request, + rename::on_prepare_rename_request, rename::on_rename_request, + signature_help::on_signature_help_request, test_run::on_test_run_request, + tests::on_tests_request, +}; + +/// LSP client will send initialization request after the server has started. +/// [InitializeParams].`initialization_options` will contain the options sent from the client. +#[derive(Debug, Deserialize, Serialize, Copy, Clone)] +pub(crate) struct LspInitializationOptions { + /// Controls whether code lens is enabled by the server + /// By default this will be set to true (enabled). + #[serde(rename = "enableCodeLens", default = "default_enable_code_lens")] + pub(crate) enable_code_lens: bool, + + #[serde(rename = "enableParsingCache", default = "default_enable_parsing_cache")] + pub(crate) enable_parsing_cache: bool, + + #[serde(rename = "inlayHints", default = "default_inlay_hints")] + pub(crate) inlay_hints: InlayHintsOptions, +} + +#[derive(Debug, Deserialize, Serialize, Copy, Clone)] +pub(crate) struct InlayHintsOptions { + #[serde(rename = "typeHints", default = "default_type_hints")] + pub(crate) type_hints: TypeHintsOptions, + + #[serde(rename = "parameterHints", default = "default_parameter_hints")] + pub(crate) parameter_hints: ParameterHintsOptions, + + #[serde(rename = "closingBraceHints", default = "default_closing_brace_hints")] + pub(crate) closing_brace_hints: ClosingBraceHintsOptions, +} + +#[derive(Debug, Deserialize, Serialize, Copy, Clone)] +pub(crate) struct TypeHintsOptions { + #[serde(rename = "enabled", default = "default_type_hints_enabled")] + pub(crate) enabled: bool, +} + +#[derive(Debug, Deserialize, Serialize, Copy, Clone)] +pub(crate) struct ParameterHintsOptions { + #[serde(rename = "enabled", default = "default_parameter_hints_enabled")] + pub(crate) enabled: bool, +} + +#[derive(Debug, Deserialize, Serialize, Copy, Clone)] +pub(crate) struct ClosingBraceHintsOptions { + #[serde(rename = "enabled", default = "default_closing_brace_hints_enabled")] + pub(crate) enabled: bool, + + #[serde(rename = "minLines", default = "default_closing_brace_min_lines")] + pub(crate) min_lines: u32, +} + +fn default_enable_code_lens() -> bool { + true +} + +fn default_enable_parsing_cache() -> bool { + true +} + +fn default_inlay_hints() -> InlayHintsOptions { + InlayHintsOptions { + type_hints: default_type_hints(), + parameter_hints: default_parameter_hints(), + closing_brace_hints: default_closing_brace_hints(), + } +} + +fn default_type_hints() -> TypeHintsOptions { + TypeHintsOptions { enabled: default_type_hints_enabled() } +} + +fn default_type_hints_enabled() -> bool { + true +} + +fn default_parameter_hints() -> ParameterHintsOptions { + ParameterHintsOptions { enabled: default_parameter_hints_enabled() } +} + +fn default_parameter_hints_enabled() -> bool { + true +} + +fn default_closing_brace_hints() -> ClosingBraceHintsOptions { + ClosingBraceHintsOptions { + enabled: default_closing_brace_hints_enabled(), + min_lines: default_closing_brace_min_lines(), + } +} + +fn default_closing_brace_hints_enabled() -> bool { + true +} + +fn default_closing_brace_min_lines() -> u32 { + 25 +} + +impl Default for LspInitializationOptions { + fn default() -> Self { + Self { + enable_code_lens: default_enable_code_lens(), + enable_parsing_cache: default_enable_parsing_cache(), + inlay_hints: default_inlay_hints(), + } + } +} + +pub(crate) fn on_initialize( + state: &mut LspState, + params: InitializeParams, +) -> impl Future> { + state.root_path = params.root_uri.and_then(|root_uri| root_uri.to_file_path().ok()); + let initialization_options: LspInitializationOptions = params + .initialization_options + .and_then(|value| serde_json::from_value(value).ok()) + .unwrap_or_default(); + state.options = initialization_options; + + async move { + let text_document_sync = TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL); + + let code_lens = if initialization_options.enable_code_lens { + Some(CodeLensOptions { resolve_provider: Some(false) }) + } else { + None + }; + + let nargo = NargoCapability { + tests: Some(NargoTestsOptions { + fetch: Some(true), + run: Some(true), + update: Some(true), + }), + }; + + Ok(InitializeResult { + capabilities: ServerCapabilities { + text_document_sync: Some(text_document_sync), + code_lens_provider: code_lens, + document_formatting_provider: true, + nargo: Some(nargo), + definition_provider: Some(lsp_types::OneOf::Left(true)), + declaration_provider: Some(DeclarationCapability::Simple(true)), + type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), + rename_provider: Some(lsp_types::OneOf::Right(lsp_types::RenameOptions { + prepare_provider: Some(true), + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + })), + references_provider: Some(lsp_types::OneOf::Right(lsp_types::ReferencesOptions { + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + })), + hover_provider: Some(lsp_types::OneOf::Right(lsp_types::HoverOptions { + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + })), + inlay_hint_provider: Some(lsp_types::OneOf::Right(lsp_types::InlayHintOptions { + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + resolve_provider: None, + })), + document_symbol_provider: Some(lsp_types::OneOf::Right( + lsp_types::DocumentSymbolOptions { + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + label: Some("Noir".to_string()), + }, + )), + completion_provider: Some(lsp_types::OneOf::Right(lsp_types::CompletionOptions { + resolve_provider: None, + trigger_characters: Some(vec![ + ".".to_string(), // For method calls + ":".to_string(), // For paths + "$".to_string(), // For $var inside `quote { ... }` + ]), + all_commit_characters: None, + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + completion_item: None, + })), + signature_help_provider: Some(lsp_types::OneOf::Right( + lsp_types::SignatureHelpOptions { + trigger_characters: Some(vec!["(".to_string(), ",".to_string()]), + retrigger_characters: None, + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + }, + )), + code_action_provider: Some(lsp_types::OneOf::Right(lsp_types::CodeActionOptions { + code_action_kinds: Some(vec![CodeActionKind::QUICKFIX]), + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + resolve_provider: None, + })), + }, + server_info: None, + }) + } +} + +pub(crate) fn on_formatting( + state: &mut LspState, + params: lsp_types::DocumentFormattingParams, +) -> impl Future>, ResponseError>> { + std::future::ready(on_formatting_inner(state, params)) +} + +fn on_formatting_inner( + state: &LspState, + params: lsp_types::DocumentFormattingParams, +) -> Result>, ResponseError> { + let path = params.text_document.uri.to_string(); + + if let Some(source) = state.input_files.get(&path) { + let (module, errors) = noirc_frontend::parse_program(source); + let is_all_warnings = errors.iter().all(ParserError::is_warning); + if !is_all_warnings { + return Ok(None); + } + + let new_text = nargo_fmt::format(source, module, &Config::default()); + + let start_position = Position { line: 0, character: 0 }; + let end_position = Position { + line: source.lines().count() as u32, + character: source.chars().count() as u32, + }; + + Ok(Some(vec![lsp_types::TextEdit { + range: lsp_types::Range::new(start_position, end_position), + new_text, + }])) + } else { + Ok(None) + } +} + +pub(crate) fn position_to_byte_index<'a, F>( + files: &'a F, + file_id: F::FileId, + position: &Position, +) -> Result +where + F: fm::codespan_files::Files<'a> + ?Sized, +{ + let source = files.source(file_id)?; + let source = source.as_ref(); + + let line_span = files.line_range(file_id, position.line as usize)?; + + let line_str = source.get(line_span.clone()); + + if let Some(line_str) = line_str { + let byte_offset = character_to_line_offset(line_str, position.character)?; + Ok(line_span.start + byte_offset) + } else { + Err(Error::InvalidCharBoundary { given: position.line as usize }) + } +} + +fn 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; + + let mut chars = line.chars(); + while let Some(ch) = chars.next() { + if character_offset == character { + let chars_off = chars.as_str().len(); + let ch_off = ch.len_utf8(); + + return Ok(line_len - chars_off - ch_off); + } + + character_offset += ch.len_utf16() as u32; + } + + // Handle positions after the last character on the line + if character_offset == character { + Ok(line_len) + } else { + Err(Error::ColumnTooLarge { given: character_offset as usize, max: line.len() }) + } +} + +pub(crate) fn to_lsp_location<'a, F>( + files: &'a F, + file_id: F::FileId, + definition_span: noirc_errors::Span, +) -> Option +where + F: fm::codespan_files::Files<'a> + ?Sized, +{ + let range = crate::byte_span_to_range(files, file_id, definition_span.into())?; + let file_name = files.name(file_id).ok()?; + + let path = file_name.to_string(); + + // `path` might be a relative path so we canonicalize it to get an absolute path + let path_buf = PathBuf::from(path); + let path_buf = path_buf.canonicalize().unwrap_or(path_buf); + + let uri = Url::from_file_path(path_buf.to_str()?).ok()?; + + Some(Location { uri, range }) +} + +pub(crate) fn on_shutdown( + _state: &mut LspState, + _params: (), +) -> impl Future> { + async { Ok(()) } +} + +pub(crate) struct ProcessRequestCallbackArgs<'a> { + location: noirc_errors::Location, + files: &'a FileMap, + interner: &'a NodeInterner, + package_cache: &'a HashMap, + crate_id: CrateId, + crate_name: String, + dependencies: &'a Vec, + def_maps: &'a BTreeMap, + usage_tracker: &'a UsageTracker, +} + +pub(crate) fn process_request( + state: &mut LspState, + text_document_position_params: TextDocumentPositionParams, + callback: F, +) -> Result +where + F: FnOnce(ProcessRequestCallbackArgs) -> T, +{ + let file_path = + text_document_position_params.text_document.uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); + let package = crate::workspace_package_for_file(&workspace, &file_path).ok_or_else(|| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find package for file") + })?; + + // In practice when `process_request` is called, a document in the project should already have been + // open so both the workspace and package cache will have data. However, just in case this isn't true + // for some reason, and also for tests (some tests just test a request without going through the full + // LSP workflow), we have a fallback where we type-check the workspace/package, then continue with + // processing the request. + let Some(workspace_cache_data) = state.workspace_cache.get(&workspace.root_dir) else { + return process_request_no_workspace_cache(state, text_document_position_params, callback); + }; + + let Some(package_cache_data) = state.package_cache.get(&package.root_dir) else { + return process_request_no_workspace_cache(state, text_document_position_params, callback); + }; + + let file_manager = &workspace_cache_data.file_manager; + let interner = &package_cache_data.node_interner; + let def_maps = &package_cache_data.def_maps; + let usage_tracker = &package_cache_data.usage_tracker; + let crate_graph = &package_cache_data.crate_graph; + let crate_id = package_cache_data.crate_id; + + let files = file_manager.as_file_map(); + + let location = position_to_location( + files, + &PathString::from(file_path), + &text_document_position_params.position, + )?; + + Ok(callback(ProcessRequestCallbackArgs { + location, + files, + interner, + package_cache: &state.package_cache, + crate_id, + crate_name: package.name.to_string(), + dependencies: &crate_graph[crate_id].dependencies, + def_maps, + usage_tracker, + })) +} + +pub(crate) fn process_request_no_workspace_cache( + state: &mut LspState, + text_document_position_params: TextDocumentPositionParams, + callback: F, +) -> Result +where + F: FnOnce(ProcessRequestCallbackArgs) -> T, +{ + let file_path = + text_document_position_params.text_document.uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); + let package = crate::workspace_package_for_file(&workspace, &file_path).ok_or_else(|| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find package for file") + })?; + + let mut workspace_file_manager = workspace.new_file_manager(); + insert_all_files_for_workspace_into_file_manager( + state, + &workspace, + &mut workspace_file_manager, + ); + let parsed_files = parse_diff(&workspace_file_manager, state); + + let (mut context, crate_id) = + crate::prepare_package(&workspace_file_manager, &parsed_files, package); + + let interner; + let def_maps; + let usage_tracker; + if let Some(package_cache) = state.package_cache.get(&package.root_dir) { + interner = &package_cache.node_interner; + def_maps = &package_cache.def_maps; + usage_tracker = &package_cache.usage_tracker; + } else { + // We ignore the warnings and errors produced by compilation while resolving the definition + let _ = noirc_driver::check_crate(&mut context, crate_id, &Default::default()); + interner = &context.def_interner; + def_maps = &context.def_maps; + usage_tracker = &context.usage_tracker; + } + + let files = workspace_file_manager.as_file_map(); + + let location = position_to_location( + files, + &PathString::from(file_path), + &text_document_position_params.position, + )?; + + Ok(callback(ProcessRequestCallbackArgs { + location, + files, + interner, + package_cache: &state.package_cache, + crate_id, + crate_name: package.name.to_string(), + dependencies: &context.crate_graph[crate_id].dependencies, + def_maps, + usage_tracker, + })) +} + +pub(crate) fn find_all_references_in_workspace( + location: noirc_errors::Location, + interner: &NodeInterner, + package_cache: &HashMap, + files: &FileMap, + include_declaration: bool, + include_self_type_name: bool, +) -> Option> { + // First find the node that's referenced by the given location, if any + let referenced = interner.find_referenced(location); + + if let Some(referenced) = referenced { + // If we found the referenced node, find its location + let referenced_location = interner.reference_location(referenced); + + // Now we find all references that point to this location, in all interners + // (there's one interner per package, and all interners in a workspace rely on the + // same FileManager so a Location/FileId in one package is the same as in another package) + let mut locations = find_all_references( + referenced_location, + interner, + files, + include_declaration, + include_self_type_name, + ); + for cache_data in package_cache.values() { + locations.extend(find_all_references( + referenced_location, + &cache_data.node_interner, + files, + include_declaration, + include_self_type_name, + )); + } + + // The LSP client usually removes duplicate loctions, but we do it here just in case they don't + locations.sort_by_key(|location| { + ( + location.uri.to_string(), + location.range.start.line, + location.range.start.character, + location.range.end.line, + location.range.end.character, + ) + }); + locations.dedup(); + + if locations.is_empty() { + None + } else { + Some(locations) + } + } else { + None + } +} + +pub(crate) fn find_all_references( + referenced_location: noirc_errors::Location, + interner: &NodeInterner, + files: &FileMap, + include_declaration: bool, + include_self_type_name: bool, +) -> Vec { + interner + .find_all_references(referenced_location, include_declaration, include_self_type_name) + .map(|locations| { + locations + .iter() + .filter_map(|location| to_lsp_location(files, location.file, location.span)) + .collect() + }) + .unwrap_or_default() +} + +#[cfg(test)] +mod initialization { + use acvm::blackbox_solver::StubbedBlackBoxSolver; + use async_lsp::ClientSocket; + use lsp_types::{ + CodeLensOptions, InitializeParams, TextDocumentSyncCapability, TextDocumentSyncKind, + }; + use tokio::test; + + use crate::{requests::on_initialize, types::ServerCapabilities, LspState}; + + #[test] + async fn test_on_initialize() { + let client = ClientSocket::new_closed(); + let mut state = LspState::new(&client, StubbedBlackBoxSolver::default()); + let params = InitializeParams::default(); + let response = on_initialize(&mut state, params).await.unwrap(); + assert!(matches!( + response.capabilities, + ServerCapabilities { + text_document_sync: Some(TextDocumentSyncCapability::Kind( + TextDocumentSyncKind::FULL + )), + code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(false) }), + document_formatting_provider: true, + .. + } + )); + assert!(response.server_info.is_none()); + } +} + +#[cfg(test)] +mod character_to_line_offset_tests { + use super::*; + + #[test] + fn test_character_to_line_offset() { + let line = "Hello, dark!"; + let character = 8; + + let result = character_to_line_offset(line, character).unwrap(); + assert_eq!(result, 8); + + // In the case of a multi-byte character, the offset should be the byte index of the character + // byte offset for 8 character (黑) is expected to be 10 + let line = "Hello, 黑!"; + let character = 8; + + let result = character_to_line_offset(line, character).unwrap(); + assert_eq!(result, 10); + } +} diff --git a/tooling/lsp/src/requests/references.rs b/tooling/lsp/src/requests/references.rs new file mode 100644 index 00000000000..6d3f92447cb --- /dev/null +++ b/tooling/lsp/src/requests/references.rs @@ -0,0 +1,173 @@ +use std::future::{self, Future}; + +use async_lsp::ResponseError; +use lsp_types::{Location, ReferenceParams}; + +use crate::LspState; + +use super::{find_all_references_in_workspace, process_request}; + +pub(crate) fn on_references_request( + state: &mut LspState, + params: ReferenceParams, +) -> impl Future>, ResponseError>> { + let include_declaration = params.context.include_declaration; + let result = process_request(state, params.text_document_position, |args| { + find_all_references_in_workspace( + args.location, + args.interner, + args.package_cache, + args.files, + include_declaration, + true, + ) + }); + future::ready(result) +} + +#[cfg(test)] +mod references_tests { + use super::*; + use crate::notifications; + use crate::test_utils::{self, search_in_file}; + use lsp_types::{ + PartialResultParams, Position, Range, ReferenceContext, TextDocumentPositionParams, Url, + WorkDoneProgressParams, + }; + use tokio::test; + + async fn check_references_succeeds( + directory: &str, + name: &str, + declaration_index: usize, + include_declaration: bool, + ) { + let (mut state, noir_text_document) = test_utils::init_lsp_server(directory).await; + + // First we find out all of the occurrences of `name` in the main.nr file. + // Note that this only works if that name doesn't show up in other places where we don't + // expect a rename, but we craft our tests to avoid that. + let ranges = search_in_file(noir_text_document.path(), name); + + // Test getting references works on any instance of the symbol. + for target_range in &ranges { + let target_position = target_range.start; + + let params = ReferenceParams { + text_document_position: TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { + uri: noir_text_document.clone(), + }, + position: target_position, + }, + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + partial_result_params: PartialResultParams { partial_result_token: None }, + context: ReferenceContext { include_declaration }, + }; + + let locations = on_references_request(&mut state, params) + .await + .expect("Could not execute on_references_request") + .unwrap(); + + let mut references_ranges: Vec<_> = + locations.iter().map(|location| location.range).collect(); + references_ranges.sort_by_key(|range| range.start.line); + + if include_declaration { + assert_eq!(ranges, references_ranges); + } else { + let mut ranges_without_declaration = ranges.clone(); + ranges_without_declaration.remove(declaration_index); + assert_eq!(ranges_without_declaration, references_ranges); + } + } + } + + #[test] + async fn test_on_references_request_including_declaration() { + check_references_succeeds("rename_function", "another_function", 0, true).await; + } + + #[test] + async fn test_on_references_request_without_including_declaration() { + check_references_succeeds("rename_function", "another_function", 0, false).await; + } + + // Ignored because making this work slows down everything, so for now things will not work + // as ideally, but they'll be fast. + // See https://github.com/noir-lang/noir/issues/5460 + #[ignore] + #[test] + async fn test_on_references_request_works_accross_workspace_packages() { + let (mut state, noir_text_document) = test_utils::init_lsp_server("workspace").await; + + // noir_text_document is always `src/main.nr` in the workspace directory, so let's go to the workspace dir + let noir_text_document = noir_text_document.to_file_path().unwrap(); + let workspace_dir = noir_text_document.parent().unwrap().parent().unwrap(); + + // Let's check that we can find references to `function_one` by doing that in the package "one" + // and getting results in the package "two" too. + let one_lib = Url::from_file_path(workspace_dir.join("one/src/lib.nr")).unwrap(); + let two_lib = Url::from_file_path(workspace_dir.join("two/src/lib.nr")).unwrap(); + + // We call this to open the document, so that the entire workspace is analyzed + let output_diagnostics = true; + + notifications::process_workspace_for_noir_document( + &mut state, + one_lib.clone(), + output_diagnostics, + ) + .unwrap(); + + let params = ReferenceParams { + text_document_position: TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { uri: one_lib.clone() }, + position: Position { line: 0, character: 7 }, + }, + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + partial_result_params: PartialResultParams { partial_result_token: None }, + context: ReferenceContext { include_declaration: true }, + }; + + let mut locations = on_references_request(&mut state, params) + .await + .expect("Could not execute on_references_request") + .unwrap(); + + // The definition, a use in "two", and a call in "two" + assert_eq!(locations.len(), 3); + + locations.sort_by_cached_key(|location| { + (location.uri.to_file_path().unwrap(), location.range.start.line) + }); + + assert_eq!(locations[0].uri, one_lib); + assert_eq!( + locations[0].range, + Range { + start: Position { line: 0, character: 7 }, + end: Position { line: 0, character: 19 }, + } + ); + + assert_eq!(locations[1].uri, two_lib); + assert_eq!( + locations[1].range, + Range { + start: Position { line: 0, character: 9 }, + end: Position { line: 0, character: 21 }, + } + ); + + assert_eq!(locations[2].uri, two_lib); + assert_eq!( + locations[2].range, + Range { + start: Position { line: 3, character: 4 }, + end: Position { line: 3, character: 16 }, + } + ); + } +} diff --git a/tooling/lsp/src/requests/rename.rs b/tooling/lsp/src/requests/rename.rs new file mode 100644 index 00000000000..95dd6b506be --- /dev/null +++ b/tooling/lsp/src/requests/rename.rs @@ -0,0 +1,207 @@ +use std::{ + collections::HashMap, + future::{self, Future}, +}; + +use async_lsp::ResponseError; +use lsp_types::{ + PrepareRenameResponse, RenameParams, TextDocumentPositionParams, TextEdit, Url, WorkspaceEdit, +}; +use noirc_frontend::node_interner::ReferenceId; + +use crate::LspState; + +use super::{find_all_references_in_workspace, process_request}; + +pub(crate) fn on_prepare_rename_request( + state: &mut LspState, + params: TextDocumentPositionParams, +) -> impl Future, ResponseError>> { + let result = process_request(state, params, |args| { + let reference_id = args.interner.reference_at_location(args.location); + let rename_possible = match reference_id { + // Rename shouldn't be possible when triggered on top of "Self" + Some(ReferenceId::Reference(_, true /* is self type name */)) => false, + Some(_) => true, + None => false, + }; + Some(PrepareRenameResponse::DefaultBehavior { default_behavior: rename_possible }) + }); + future::ready(result) +} + +pub(crate) fn on_rename_request( + state: &mut LspState, + params: RenameParams, +) -> impl Future, ResponseError>> { + let result = process_request(state, params.text_document_position, |args| { + let rename_changes = find_all_references_in_workspace( + args.location, + args.interner, + args.package_cache, + args.files, + true, + false, + ) + .map(|locations| { + let rs = locations.iter().fold( + HashMap::new(), + |mut acc: HashMap>, location| { + let edit = + TextEdit { range: location.range, new_text: params.new_name.clone() }; + acc.entry(location.uri.clone()).or_default().push(edit); + acc + }, + ); + rs + }); + + let response = WorkspaceEdit { + changes: rename_changes, + document_changes: None, + change_annotations: None, + }; + + Some(response) + }); + future::ready(result) +} + +#[cfg(test)] +mod rename_tests { + use super::*; + use crate::test_utils::{self, search_in_file}; + use lsp_types::{Range, WorkDoneProgressParams}; + use tokio::test; + + async fn check_rename_succeeds(directory: &str, name: &str) { + let (mut state, noir_text_document) = test_utils::init_lsp_server(directory).await; + + // First we find out all of the occurrences of `name` in the main.nr file. + // Note that this only works if that name doesn't show up in other places where we don't + // expect a rename, but we craft our tests to avoid that. + let ranges = search_in_file(noir_text_document.path(), name); + + // Test renaming works on any instance of the symbol. + for target_range in &ranges { + let target_position = target_range.start; + + let params = RenameParams { + text_document_position: TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { + uri: noir_text_document.clone(), + }, + position: target_position, + }, + new_name: "renamed_function".to_string(), + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + }; + + let response = on_rename_request(&mut state, params) + .await + .expect("Could not execute on_prepare_rename_request") + .unwrap(); + + let changes = response.changes.expect("Expected to find rename changes"); + let mut changes: Vec = + changes.values().flatten().map(|edit| edit.range).collect(); + changes.sort_by_key(|range| (range.start.line, range.start.character)); + if changes != ranges { + let extra_in_changes: Vec<_> = + changes.iter().filter(|range| !ranges.contains(range)).collect(); + let extra_in_ranges: Vec<_> = + ranges.iter().filter(|range| !changes.contains(range)).collect(); + panic!("Rename locations did not match.\nThese renames were not found: {:?}\nThese renames should not have been found: {:?}", extra_in_ranges, extra_in_changes); + } + assert_eq!(changes, ranges); + } + } + + #[test] + async fn test_on_prepare_rename_request_cannot_be_applied_if_there_are_no_matches() { + let (mut state, noir_text_document) = test_utils::init_lsp_server("rename_function").await; + + let params = TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { uri: noir_text_document }, + position: lsp_types::Position { line: 0, character: 0 }, // This is at the "f" of an "fn" keyword + }; + + let response = on_prepare_rename_request(&mut state, params) + .await + .expect("Could not execute on_prepare_rename_request"); + + assert_eq!( + response, + Some(PrepareRenameResponse::DefaultBehavior { default_behavior: false }) + ); + } + + #[test] + async fn test_on_prepare_rename_request_cannot_be_applied_on_self_type_name() { + let (mut state, noir_text_document) = test_utils::init_lsp_server("rename_struct").await; + + let params = TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { uri: noir_text_document }, + position: lsp_types::Position { line: 11, character: 24 }, // At "Self" + }; + + let response = on_prepare_rename_request(&mut state, params) + .await + .expect("Could not execute on_prepare_rename_request"); + + assert_eq!( + response, + Some(PrepareRenameResponse::DefaultBehavior { default_behavior: false }) + ); + } + + #[test] + async fn test_rename_function() { + check_rename_succeeds("rename_function", "another_function").await; + } + + #[test] + async fn test_rename_qualified_function() { + check_rename_succeeds("rename_qualified_function", "bar").await; + } + + #[test] + async fn test_rename_function_in_use_statement() { + check_rename_succeeds("rename_function_use", "some_function").await; + } + + #[test] + async fn test_rename_method() { + check_rename_succeeds("rename_function", "some_method").await; + } + + #[test] + async fn test_rename_struct() { + check_rename_succeeds("rename_struct", "Foo").await; + } + + #[test] + async fn test_rename_trait() { + check_rename_succeeds("rename_trait", "Foo").await; + } + + #[test] + async fn test_rename_type_alias() { + check_rename_succeeds("rename_type_alias", "Bar").await; + } + + #[test] + async fn test_rename_global() { + check_rename_succeeds("rename_global", "FOO").await; + } + + #[test] + async fn test_rename_local_variable() { + check_rename_succeeds("local_variable", "some_var").await; + } + + #[test] + async fn test_rename_struct_member() { + check_rename_succeeds("struct_member", "some_member").await; + } +} diff --git a/tooling/lsp/src/requests/signature_help.rs b/tooling/lsp/src/requests/signature_help.rs new file mode 100644 index 00000000000..c0d40656c19 --- /dev/null +++ b/tooling/lsp/src/requests/signature_help.rs @@ -0,0 +1,401 @@ +use std::future::{self, Future}; + +use async_lsp::ResponseError; +use fm::{FileId, PathString}; +use lsp_types::{ + ParameterInformation, ParameterLabel, SignatureHelp, SignatureHelpParams, SignatureInformation, +}; +use noirc_errors::{Location, Span}; +use noirc_frontend::{ + ast::{ + CallExpression, ConstrainKind, ConstrainStatement, Expression, FunctionReturnType, + MethodCallExpression, Statement, Visitor, + }, + hir_def::{function::FuncMeta, stmt::HirPattern}, + node_interner::{NodeInterner, ReferenceId}, + parser::Item, + ParsedModule, Type, +}; + +use crate::{utils, LspState}; + +use super::process_request; + +mod tests; + +pub(crate) fn on_signature_help_request( + state: &mut LspState, + params: SignatureHelpParams, +) -> impl Future, ResponseError>> { + let uri = params.text_document_position_params.clone().text_document.uri; + + let result = process_request(state, params.text_document_position_params.clone(), |args| { + let path = PathString::from_path(uri.to_file_path().unwrap()); + args.files.get_file_id(&path).and_then(|file_id| { + utils::position_to_byte_index( + args.files, + file_id, + ¶ms.text_document_position_params.position, + ) + .and_then(|byte_index| { + let file = args.files.get_file(file_id).unwrap(); + let source = file.source(); + let (parsed_module, _errors) = noirc_frontend::parse_program(source); + + let mut finder = SignatureFinder::new(file_id, byte_index, args.interner); + finder.find(&parsed_module) + }) + }) + }); + future::ready(result) +} + +struct SignatureFinder<'a> { + file: FileId, + byte_index: usize, + interner: &'a NodeInterner, + signature_help: Option, +} + +impl<'a> SignatureFinder<'a> { + fn new(file: FileId, byte_index: usize, interner: &'a NodeInterner) -> Self { + Self { file, byte_index, interner, signature_help: None } + } + + fn find(&mut self, parsed_module: &ParsedModule) -> Option { + parsed_module.accept(self); + + self.signature_help.clone() + } + + fn try_compute_signature_help( + &mut self, + arguments: &[Expression], + arguments_span: Span, + name_span: Span, + has_self: bool, + ) { + if self.signature_help.is_some() { + return; + } + + if !self.includes_span(arguments_span) { + return; + } + + let active_parameter = self.compute_active_parameter(arguments); + let location = Location::new(name_span, self.file); + + // Check if the call references a named function + if let Some(ReferenceId::Function(func_id)) = self.interner.find_referenced(location) { + let name = self.interner.function_name(&func_id); + let func_meta = self.interner.function_meta(&func_id); + + let signature_information = + self.func_meta_signature_information(func_meta, name, active_parameter, has_self); + self.set_signature_help(signature_information); + return; + } + + // Otherwise, the call must be a reference to an fn type + if let Some(mut typ) = self.interner.type_at_location(location) { + typ = typ.follow_bindings(); + if let Type::Forall(_, forall_typ) = typ { + typ = *forall_typ; + } + if let Type::Function(args, return_type, _, unconstrained) = typ { + let signature_information = self.function_type_signature_information( + &args, + &return_type, + unconstrained, + active_parameter, + ); + self.set_signature_help(signature_information); + } + } + } + + fn func_meta_signature_information( + &self, + func_meta: &FuncMeta, + name: &str, + active_parameter: Option, + has_self: bool, + ) -> SignatureInformation { + let mut label = String::new(); + let mut parameters = Vec::new(); + + label.push_str("fn "); + label.push_str(name); + label.push('('); + for (index, (pattern, typ, _)) in func_meta.parameters.0.iter().enumerate() { + if index > 0 { + label.push_str(", "); + } + + if has_self && index == 0 { + if let Type::MutableReference(..) = typ { + label.push_str("&mut self"); + } else { + label.push_str("self"); + } + } else { + let parameter_start = label.chars().count(); + + self.hir_pattern_to_argument(pattern, &mut label); + label.push_str(": "); + label.push_str(&typ.to_string()); + + let parameter_end = label.chars().count(); + + parameters.push(ParameterInformation { + label: ParameterLabel::LabelOffsets([ + parameter_start as u32, + parameter_end as u32, + ]), + documentation: None, + }); + } + } + label.push(')'); + + match &func_meta.return_type { + FunctionReturnType::Default(_) => (), + FunctionReturnType::Ty(typ) => { + label.push_str(" -> "); + label.push_str(&typ.to_string()); + } + } + + SignatureInformation { + label, + documentation: None, + parameters: Some(parameters), + active_parameter, + } + } + + fn function_type_signature_information( + &self, + args: &[Type], + return_type: &Type, + unconstrained: bool, + active_parameter: Option, + ) -> SignatureInformation { + let mut label = String::new(); + let mut parameters = Vec::new(); + + if unconstrained { + label.push_str("unconstrained "); + } + label.push_str("fn("); + for (index, typ) in args.iter().enumerate() { + if index > 0 { + label.push_str(", "); + } + + let parameter_start = label.chars().count(); + label.push_str(&typ.to_string()); + let parameter_end = label.chars().count(); + + parameters.push(ParameterInformation { + label: ParameterLabel::LabelOffsets([parameter_start as u32, parameter_end as u32]), + documentation: None, + }); + } + label.push(')'); + + if let Type::Unit = return_type { + // Nothing + } else { + label.push_str(" -> "); + label.push_str(&return_type.to_string()); + } + + SignatureInformation { + label, + documentation: None, + parameters: Some(parameters), + active_parameter, + } + } + + fn assert_signature_information(&self, active_parameter: Option) -> SignatureInformation { + self.hardcoded_signature_information( + active_parameter, + "assert", + &["predicate: bool", "[failure_message: str]"], + ) + } + + fn assert_eq_signature_information( + &self, + active_parameter: Option, + ) -> SignatureInformation { + self.hardcoded_signature_information( + active_parameter, + "assert_eq", + &["lhs: T", "rhs: T", "[failure_message: str]"], + ) + } + + fn hardcoded_signature_information( + &self, + active_parameter: Option, + name: &str, + arguments: &[&str], + ) -> SignatureInformation { + let mut label = String::new(); + let mut parameters = Vec::new(); + + label.push_str(name); + label.push('('); + for (index, typ) in arguments.iter().enumerate() { + if index > 0 { + label.push_str(", "); + } + + let parameter_start = label.chars().count(); + label.push_str(typ); + let parameter_end = label.chars().count(); + + parameters.push(ParameterInformation { + label: ParameterLabel::LabelOffsets([parameter_start as u32, parameter_end as u32]), + documentation: None, + }); + } + label.push(')'); + + SignatureInformation { + label, + documentation: None, + parameters: Some(parameters), + active_parameter, + } + } + + fn hir_pattern_to_argument(&self, pattern: &HirPattern, text: &mut String) { + match pattern { + HirPattern::Identifier(hir_ident) => { + text.push_str(self.interner.definition_name(hir_ident.id)); + } + HirPattern::Mutable(pattern, _) => self.hir_pattern_to_argument(pattern, text), + HirPattern::Tuple(_, _) | HirPattern::Struct(_, _, _) => text.push('_'), + } + } + + fn set_signature_help(&mut self, signature_information: SignatureInformation) { + let signature_help = SignatureHelp { + active_parameter: signature_information.active_parameter, + signatures: vec![signature_information], + active_signature: Some(0), + }; + self.signature_help = Some(signature_help); + } + + fn compute_active_parameter(&self, arguments: &[Expression]) -> Option { + let mut active_parameter = None; + for (index, arg) in arguments.iter().enumerate() { + if self.includes_span(arg.span) || arg.span.start() as usize >= self.byte_index { + active_parameter = Some(index as u32); + break; + } + } + + if active_parameter.is_none() { + active_parameter = Some(arguments.len() as u32); + } + + active_parameter + } + + fn includes_span(&self, span: Span) -> bool { + span.start() as usize <= self.byte_index && self.byte_index <= span.end() as usize + } +} + +impl<'a> Visitor for SignatureFinder<'a> { + fn visit_item(&mut self, item: &Item) -> bool { + self.includes_span(item.span) + } + + fn visit_statement(&mut self, statement: &Statement) -> bool { + self.includes_span(statement.span) + } + + fn visit_expression(&mut self, expression: &Expression) -> bool { + self.includes_span(expression.span) + } + + fn visit_call_expression(&mut self, call_expression: &CallExpression, span: Span) -> bool { + call_expression.accept_children(self); + + let arguments_span = Span::from(call_expression.func.span.end() + 1..span.end() - 1); + let span = call_expression.func.span; + let name_span = Span::from(span.end() - 1..span.end()); + let has_self = false; + + self.try_compute_signature_help( + &call_expression.arguments, + arguments_span, + name_span, + has_self, + ); + + false + } + + fn visit_method_call_expression( + &mut self, + method_call_expression: &MethodCallExpression, + span: Span, + ) -> bool { + method_call_expression.accept_children(self); + + let arguments_span = + Span::from(method_call_expression.method_name.span().end() + 1..span.end() - 1); + let name_span = method_call_expression.method_name.span(); + let has_self = true; + + self.try_compute_signature_help( + &method_call_expression.arguments, + arguments_span, + name_span, + has_self, + ); + + false + } + + fn visit_constrain_statement(&mut self, constrain_statement: &ConstrainStatement) -> bool { + constrain_statement.accept_children(self); + + if self.signature_help.is_some() { + return false; + } + + let kind_len = constrain_statement.kind.to_string().len() as u32; + let span = constrain_statement.span; + let arguments_span = Span::from(span.start() + kind_len + 1..span.end() - 1); + + if !self.includes_span(arguments_span) { + return false; + } + + let active_parameter = self.compute_active_parameter(&constrain_statement.arguments); + + match constrain_statement.kind { + ConstrainKind::Assert => { + let signature_information = self.assert_signature_information(active_parameter); + self.set_signature_help(signature_information); + } + ConstrainKind::AssertEq => { + let signature_information = self.assert_eq_signature_information(active_parameter); + self.set_signature_help(signature_information); + } + ConstrainKind::Constrain => (), + } + + false + } +} diff --git a/tooling/lsp/src/requests/signature_help/tests.rs b/tooling/lsp/src/requests/signature_help/tests.rs new file mode 100644 index 00000000000..4b3f3c38156 --- /dev/null +++ b/tooling/lsp/src/requests/signature_help/tests.rs @@ -0,0 +1,243 @@ +#[cfg(test)] +mod signature_help_tests { + use crate::{ + notifications::on_did_open_text_document, requests::on_signature_help_request, test_utils, + }; + + use lsp_types::{ + DidOpenTextDocumentParams, ParameterLabel, Position, SignatureHelp, SignatureHelpParams, + TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams, + WorkDoneProgressParams, + }; + use tokio::test; + + async fn get_signature_help(src: &str) -> SignatureHelp { + let (mut state, noir_text_document) = test_utils::init_lsp_server("document_symbol").await; + + let (line, column) = src + .lines() + .enumerate() + .find_map(|(line_index, line)| { + line.find(">|<").map(|char_index| (line_index, char_index)) + }) + .expect("Expected to find one >|< in the source code"); + + let src = src.replace(">|<", ""); + + on_did_open_text_document( + &mut state, + DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: noir_text_document.clone(), + language_id: "noir".to_string(), + version: 0, + text: src.to_string(), + }, + }, + ); + + on_signature_help_request( + &mut state, + SignatureHelpParams { + context: None, + text_document_position_params: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: noir_text_document }, + position: Position { line: line as u32, character: column as u32 }, + }, + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + }, + ) + .await + .expect("Could not execute on_signature_help_request") + .unwrap() + } + + fn check_label(signature_label: &str, parameter_label: &ParameterLabel, expected_string: &str) { + let ParameterLabel::LabelOffsets(offsets) = parameter_label else { + panic!("Expected label to be LabelOffsets, got {:?}", parameter_label); + }; + + assert_eq!(&signature_label[offsets[0] as usize..offsets[1] as usize], expected_string); + } + + #[test] + async fn test_signature_help_for_call_at_first_argument() { + let src = r#" + fn foo(x: i32, y: Field) -> u32 { 0 } + fn wrapper(x: u32) {} + + fn bar() { + wrapper(foo(>|<1, 2)); + } + "#; + + let signature_help = get_signature_help(src).await; + assert_eq!(signature_help.signatures.len(), 1); + + let signature = &signature_help.signatures[0]; + assert_eq!(signature.label, "fn foo(x: i32, y: Field) -> u32"); + + let params = signature.parameters.as_ref().unwrap(); + assert_eq!(params.len(), 2); + + check_label(&signature.label, ¶ms[0].label, "x: i32"); + check_label(&signature.label, ¶ms[1].label, "y: Field"); + + assert_eq!(signature.active_parameter, Some(0)); + } + + #[test] + async fn test_signature_help_for_call_between_arguments() { + let src = r#" + fn foo(x: i32, y: Field) -> u32 { 0 } + + fn bar() { + foo(1,>|< 2); + } + "#; + + let signature_help = get_signature_help(src).await; + assert_eq!(signature_help.signatures.len(), 1); + + let signature = &signature_help.signatures[0]; + assert_eq!(signature.active_parameter, Some(1)); + } + + #[test] + async fn test_signature_help_for_call_at_second_argument() { + let src = r#" + fn foo(x: i32, y: Field) -> u32 { 0 } + + fn bar() { + foo(1, >|<2); + } + "#; + + let signature_help = get_signature_help(src).await; + assert_eq!(signature_help.signatures.len(), 1); + + let signature = &signature_help.signatures[0]; + assert_eq!(signature.active_parameter, Some(1)); + } + + #[test] + async fn test_signature_help_for_call_past_last_argument() { + let src = r#" + fn foo(x: i32, y: Field) -> u32 { 0 } + + fn bar() { + foo(1, 2, >|<); + } + "#; + + let signature_help = get_signature_help(src).await; + assert_eq!(signature_help.signatures.len(), 1); + + let signature = &signature_help.signatures[0]; + assert_eq!(signature.active_parameter, Some(2)); + } + + #[test] + async fn test_signature_help_for_method_call() { + let src = r#" + struct Foo {} + + impl Foo { + fn foo(self, x: i32, y: Field) -> u32 { 0 } + } + + fn wrapper(x: u32) {} + + fn bar(f: Foo) { + wrapper(f.foo(>|<1, 2)); + } + "#; + + let signature_help = get_signature_help(src).await; + assert_eq!(signature_help.signatures.len(), 1); + + let signature = &signature_help.signatures[0]; + assert_eq!(signature.label, "fn foo(self, x: i32, y: Field) -> u32"); + + let params = signature.parameters.as_ref().unwrap(); + assert_eq!(params.len(), 2); + + check_label(&signature.label, ¶ms[0].label, "x: i32"); + check_label(&signature.label, ¶ms[1].label, "y: Field"); + + assert_eq!(signature.active_parameter, Some(0)); + } + + #[test] + async fn test_signature_help_for_fn_call() { + let src = r#" + fn foo(x: i32, y: Field) -> u32 { 0 } + + fn bar() { + let f = foo; + f(>|<1, 2); + } + "#; + + let signature_help = get_signature_help(src).await; + assert_eq!(signature_help.signatures.len(), 1); + + let signature = &signature_help.signatures[0]; + assert_eq!(signature.label, "fn(i32, Field) -> u32"); + + let params = signature.parameters.as_ref().unwrap(); + assert_eq!(params.len(), 2); + + check_label(&signature.label, ¶ms[0].label, "i32"); + check_label(&signature.label, ¶ms[1].label, "Field"); + + assert_eq!(signature.active_parameter, Some(0)); + } + + #[test] + async fn test_signature_help_for_assert() { + let src = r#" + fn bar() { + assert(>|<1, "hello"); + } + "#; + + let signature_help = get_signature_help(src).await; + assert_eq!(signature_help.signatures.len(), 1); + + let signature = &signature_help.signatures[0]; + assert_eq!(signature.label, "assert(predicate: bool, [failure_message: str])"); + + let params = signature.parameters.as_ref().unwrap(); + assert_eq!(params.len(), 2); + + check_label(&signature.label, ¶ms[0].label, "predicate: bool"); + check_label(&signature.label, ¶ms[1].label, "[failure_message: str]"); + + assert_eq!(signature.active_parameter, Some(0)); + } + + #[test] + async fn test_signature_help_for_assert_eq() { + let src = r#" + fn bar() { + assert_eq(>|])"); + + let params = signature.parameters.as_ref().unwrap(); + assert_eq!(params.len(), 3); + + check_label(&signature.label, ¶ms[0].label, "lhs: T"); + check_label(&signature.label, ¶ms[1].label, "rhs: T"); + check_label(&signature.label, ¶ms[2].label, "[failure_message: str]"); + + assert_eq!(signature.active_parameter, Some(0)); + } +} diff --git a/tooling/lsp/src/requests/test_run.rs b/tooling/lsp/src/requests/test_run.rs new file mode 100644 index 00000000000..bd53526298e --- /dev/null +++ b/tooling/lsp/src/requests/test_run.rs @@ -0,0 +1,133 @@ +use std::future::{self, Future}; + +use crate::insert_all_files_for_workspace_into_file_manager; +use async_lsp::{ErrorCode, ResponseError}; +use nargo::{ + foreign_calls::DefaultForeignCallBuilder, + ops::{run_test, TestStatus}, + PrintOutput, +}; +use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_driver::{check_crate, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_frontend::hir::FunctionNameMatch; + +use crate::{ + parse_diff, + types::{NargoTestRunParams, NargoTestRunResult}, + LspState, +}; + +pub(crate) fn on_test_run_request( + state: &mut LspState, + params: NargoTestRunParams, +) -> impl Future> { + future::ready(on_test_run_request_inner(state, params)) +} + +fn on_test_run_request_inner( + state: &mut LspState, + params: NargoTestRunParams, +) -> Result { + let root_path = state.root_path.as_deref().ok_or_else(|| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find project root") + })?; + + let toml_path = find_package_manifest(root_path, root_path).map_err(|err| { + // If we cannot find a manifest, we can't run the test + ResponseError::new(ErrorCode::REQUEST_FAILED, err) + })?; + + let crate_name = params.id.crate_name(); + let function_name = params.id.function_name(); + + let workspace = resolve_workspace_from_toml( + &toml_path, + PackageSelection::Selected(crate_name.clone()), + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + ) + .map_err(|err| { + // If we found a manifest, but the workspace is invalid, we raise an error about it + ResponseError::new(ErrorCode::REQUEST_FAILED, err) + })?; + + let mut workspace_file_manager = workspace.new_file_manager(); + insert_all_files_for_workspace_into_file_manager( + state, + &workspace, + &mut workspace_file_manager, + ); + let parsed_files = parse_diff(&workspace_file_manager, state); + + // Since we filtered on crate name, this should be the only item in the iterator + match workspace.into_iter().next() { + Some(package) => { + let (mut context, crate_id) = + crate::prepare_package(&workspace_file_manager, &parsed_files, package); + if check_crate(&mut context, crate_id, &Default::default()).is_err() { + let result = NargoTestRunResult { + id: params.id.clone(), + result: "error".to_string(), + message: Some("The project failed to compile".into()), + }; + return Ok(result); + }; + + let test_functions = context.get_all_test_functions_in_crate_matching( + &crate_id, + FunctionNameMatch::Exact(function_name), + ); + + let (_, test_function) = test_functions.into_iter().next().ok_or_else(|| { + ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not locate test named: {function_name} in {crate_name}"), + ) + })?; + + let test_result = run_test( + &state.solver, + &mut context, + &test_function, + PrintOutput::Stdout, + &CompileOptions::default(), + |output, base| { + DefaultForeignCallBuilder { + output, + enable_mocks: true, + resolver_url: None, // NB without this the root and package don't do anything. + root_path: Some(workspace.root_dir.clone()), + package_name: Some(package.name.to_string()), + } + .build_with_base(base) + }, + ); + let result = match test_result { + TestStatus::Pass => NargoTestRunResult { + id: params.id.clone(), + result: "pass".to_string(), + message: None, + }, + TestStatus::Fail { message, .. } => NargoTestRunResult { + id: params.id.clone(), + result: "fail".to_string(), + message: Some(message), + }, + TestStatus::Skipped => NargoTestRunResult { + id: params.id.clone(), + result: "skipped".to_string(), + message: None, + }, + TestStatus::CompileError(diag) => NargoTestRunResult { + id: params.id.clone(), + result: "error".to_string(), + message: Some(diag.diagnostic.message), + }, + }; + Ok(result) + } + None => Err(ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not locate package named: {crate_name}"), + )), + } +} diff --git a/tooling/lsp/src/requests/tests.rs b/tooling/lsp/src/requests/tests.rs new file mode 100644 index 00000000000..81910bebedb --- /dev/null +++ b/tooling/lsp/src/requests/tests.rs @@ -0,0 +1,81 @@ +use std::future::{self, Future}; + +use crate::insert_all_files_for_workspace_into_file_manager; +use async_lsp::{ErrorCode, LanguageClient, ResponseError}; +use lsp_types::{LogMessageParams, MessageType}; +use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; + +use crate::{ + get_package_tests_in_crate, parse_diff, + types::{NargoPackageTests, NargoTestsParams, NargoTestsResult}, + LspState, +}; + +pub(crate) fn on_tests_request( + state: &mut LspState, + params: NargoTestsParams, +) -> impl Future> { + future::ready(on_tests_request_inner(state, params)) +} + +fn on_tests_request_inner( + state: &mut LspState, + _params: NargoTestsParams, +) -> Result { + let root_path = state.root_path.as_deref().ok_or_else(|| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find project root") + })?; + + let toml_path = match find_package_manifest(root_path, root_path) { + Ok(toml_path) => toml_path, + Err(err) => { + // If we cannot find a manifest, we log a warning but return no code lenses + // We can reconsider this when we can build a file without the need for a Nargo.toml file to resolve deps + let _ = state.client.log_message(LogMessageParams { + typ: MessageType::WARNING, + message: err.to_string(), + }); + return Ok(None); + } + }; + + let workspace = resolve_workspace_from_toml( + &toml_path, + PackageSelection::All, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + ) + .map_err(|err| { + // If we found a manifest, but the workspace is invalid, we raise an error about it + ResponseError::new(ErrorCode::REQUEST_FAILED, err) + })?; + + let mut workspace_file_manager = workspace.new_file_manager(); + insert_all_files_for_workspace_into_file_manager( + state, + &workspace, + &mut workspace_file_manager, + ); + let parsed_files = parse_diff(&workspace_file_manager, state); + + let package_tests: Vec<_> = workspace + .into_iter() + .filter_map(|package| { + let (mut context, crate_id) = + crate::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, &Default::default()); + + // 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) + .map(|tests| NargoPackageTests { package: package.name.to_string(), tests }) + }) + .collect(); + + if package_tests.is_empty() { + Ok(None) + } else { + Ok(Some(package_tests)) + } +} diff --git a/tooling/lsp/src/solver.rs b/tooling/lsp/src/solver.rs new file mode 100644 index 00000000000..df5c8eeb44f --- /dev/null +++ b/tooling/lsp/src/solver.rs @@ -0,0 +1,47 @@ +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>); + +impl BlackBoxFunctionSolver for WrapperSolver { + fn pedantic_solving(&self) -> bool { + self.0.pedantic_solving() + } + + fn multi_scalar_mul( + &self, + 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 ec_add( + &self, + input1_x: &acvm::FieldElement, + input1_y: &acvm::FieldElement, + input1_infinite: &acvm::FieldElement, + input2_x: &acvm::FieldElement, + input2_y: &acvm::FieldElement, + 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( + &self, + inputs: &[acvm::FieldElement], + len: u32, + ) -> Result, acvm::BlackBoxResolutionError> { + self.0.poseidon2_permutation(inputs, len) + } +} diff --git a/tooling/lsp/src/test_utils.rs b/tooling/lsp/src/test_utils.rs new file mode 100644 index 00000000000..c2c19b0efc7 --- /dev/null +++ b/tooling/lsp/src/test_utils.rs @@ -0,0 +1,60 @@ +use crate::LspState; +use acvm::blackbox_solver::StubbedBlackBoxSolver; +use async_lsp::ClientSocket; +use lsp_types::{Position, Range, Url}; + +pub(crate) async fn init_lsp_server(directory: &str) -> (LspState, Url) { + let client = ClientSocket::new_closed(); + let mut state = LspState::new(&client, StubbedBlackBoxSolver::default()); + + let root_path = std::env::current_dir() + .unwrap() + .join("test_programs") + .join(directory) + .canonicalize() + .expect("Could not resolve root path"); + let noir_text_document = Url::from_file_path(root_path.join("src/main.nr").as_path()) + .expect("Could not convert text document path to URI"); + let root_uri = + Some(Url::from_file_path(root_path.as_path()).expect("Could not convert root path to URI")); + + #[allow(deprecated)] + let initialize_params = lsp_types::InitializeParams { + process_id: Default::default(), + root_path: None, + root_uri, + initialization_options: None, + capabilities: Default::default(), + trace: Some(lsp_types::TraceValue::Verbose), + workspace_folders: None, + client_info: None, + locale: None, + }; + + let _initialize_response = crate::requests::on_initialize(&mut state, initialize_params) + .await + .expect("Could not initialize LSP server"); + + (state, noir_text_document) +} + +/// Searches for all instances of `search_string` in file `file_name` and returns a list of their locations. +pub(crate) fn search_in_file(filename: &str, search_string: &str) -> Vec { + let file_contents = std::fs::read_to_string(filename) + .unwrap_or_else(|_| panic!("Couldn't read file {}", filename)); + let file_lines: Vec<&str> = file_contents.lines().collect(); + file_lines + .iter() + .enumerate() + .flat_map(|(line_num, line)| { + line.match_indices(search_string).map(move |(index, _)| { + let start = Position { line: line_num as u32, character: index as u32 }; + let end = Position { + line: line_num as u32, + character: (index + search_string.len()) as u32, + }; + Range { start, end } + }) + }) + .collect() +} diff --git a/tooling/lsp/src/tests.rs b/tooling/lsp/src/tests.rs new file mode 100644 index 00000000000..7f2d48cd23f --- /dev/null +++ b/tooling/lsp/src/tests.rs @@ -0,0 +1,33 @@ +#![cfg(test)] + +use lsp_types::TextEdit; + +pub(crate) fn apply_text_edit(src: &str, text_edit: &TextEdit) -> String { + let mut lines: Vec<_> = src.lines().collect(); + assert_eq!(text_edit.range.start.line, text_edit.range.end.line); + + let mut line = lines[text_edit.range.start.line as usize].to_string(); + line.replace_range( + text_edit.range.start.character as usize..text_edit.range.end.character as usize, + &text_edit.new_text, + ); + lines[text_edit.range.start.line as usize] = &line; + lines.join("\n") +} + +pub(crate) fn apply_text_edits(src: &str, text_edits: &[TextEdit]) -> String { + let mut text = src.to_string(); + + // Text edits must be applied from last to first, otherwise if we apply a text edit + // that comes before another one, that other one becomes invalid (it will edit the wrong + // piece of code). + let mut text_edits = text_edits.to_vec(); + text_edits.sort_by_key(|edit| (edit.range.start.line, edit.range.start.character)); + text_edits.reverse(); + + for text_edit in text_edits { + text = apply_text_edit(&text, &text_edit); + } + + text +} diff --git a/tooling/lsp/src/trait_impl_method_stub_generator.rs b/tooling/lsp/src/trait_impl_method_stub_generator.rs new file mode 100644 index 00000000000..2ae0d526f3e --- /dev/null +++ b/tooling/lsp/src/trait_impl_method_stub_generator.rs @@ -0,0 +1,453 @@ +use std::collections::BTreeMap; + +use noirc_frontend::{ + ast::NoirTraitImpl, + graph::CrateId, + hir::def_map::ModuleDefId, + hir::{ + def_map::{CrateDefMap, ModuleId}, + type_check::generics::TraitGenerics, + }, + hir_def::{function::FuncMeta, stmt::HirPattern, traits::Trait}, + node_interner::{FunctionModifiers, NodeInterner, ReferenceId}, + Kind, ResolvedGeneric, Type, +}; + +use crate::modules::relative_module_id_path; + +pub(crate) struct TraitImplMethodStubGenerator<'a> { + name: &'a str, + func_meta: &'a FuncMeta, + modifiers: &'a FunctionModifiers, + trait_: &'a Trait, + noir_trait_impl: &'a NoirTraitImpl, + interner: &'a NodeInterner, + def_maps: &'a BTreeMap, + module_id: ModuleId, + indent: usize, + body: Option, + string: String, +} + +impl<'a> TraitImplMethodStubGenerator<'a> { + #[allow(clippy::too_many_arguments)] + pub(crate) fn new( + name: &'a str, + func_meta: &'a FuncMeta, + modifiers: &'a FunctionModifiers, + trait_: &'a Trait, + noir_trait_impl: &'a NoirTraitImpl, + interner: &'a NodeInterner, + def_maps: &'a BTreeMap, + module_id: ModuleId, + indent: usize, + ) -> Self { + Self { + name, + func_meta, + modifiers, + trait_, + noir_trait_impl, + interner, + def_maps, + module_id, + indent, + body: None, + string: String::new(), + } + } + + /// Sets the body to include in the stub method. By default an empty body will be generated. + pub(crate) fn set_body(&mut self, body: String) { + self.body = Some(body); + } + + pub(crate) fn generate(&mut self) -> String { + let indent_string = " ".repeat(self.indent); + + self.string.push_str(&indent_string); + if self.modifiers.is_unconstrained { + self.string.push_str("unconstrained "); + } + self.string.push_str("fn "); + self.string.push_str(self.name); + self.append_resolved_generics(&self.func_meta.direct_generics); + self.string.push('('); + for (index, (pattern, typ, _visibility)) in self.func_meta.parameters.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + if self.append_pattern(pattern) { + self.string.push_str(": "); + self.append_type(typ); + } + } + self.string.push(')'); + + let return_type = self.func_meta.return_type(); + if return_type != &Type::Unit { + self.string.push_str(" -> "); + self.append_type(return_type); + } + + if !self.func_meta.trait_constraints.is_empty() { + self.string.push_str(" where "); + for (index, constraint) in self.func_meta.trait_constraints.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(&constraint.typ); + self.string.push_str(": "); + let trait_ = self.interner.get_trait(constraint.trait_bound.trait_id); + self.string.push_str(&trait_.name.0.contents); + self.append_trait_generics(&constraint.trait_bound.trait_generics); + } + } + + self.string.push_str(" {\n"); + + if let Some(body) = &self.body { + let body_indent_string = " ".repeat(self.indent + 4); + self.string.push_str(&body_indent_string); + self.string.push_str(body); + self.string.push('\n'); + self.string.push_str(&indent_string); + } + + self.string.push_str("}\n"); + std::mem::take(&mut self.string) + } + + /// Appends a pattern and returns true if this was not the self type + fn append_pattern(&mut self, pattern: &HirPattern) -> bool { + match pattern { + HirPattern::Identifier(hir_ident) => { + let definition = self.interner.definition(hir_ident.id); + self.string.push_str(&definition.name); + &definition.name != "self" + } + HirPattern::Mutable(pattern, _) => { + self.string.push_str("mut "); + self.append_pattern(pattern) + } + HirPattern::Tuple(patterns, _) => { + self.string.push('('); + for (index, pattern) in patterns.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_pattern(pattern); + } + self.string.push(')'); + true + } + HirPattern::Struct(typ, patterns, _) => { + self.append_type(typ); + self.string.push_str(" { "); + for (index, (name, _pattern)) in patterns.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.string.push_str(&name.0.contents); + } + self.string.push_str(" }"); + true + } + } + } + + fn append_type(&mut self, typ: &Type) { + match typ { + Type::FieldElement => self.string.push_str("Field"), + Type::Array(n, e) => { + self.string.push('['); + self.append_type(e); + self.string.push_str("; "); + self.append_type(n); + self.string.push(']'); + } + Type::Slice(typ) => { + self.string.push('['); + self.append_type(typ); + self.string.push(']'); + } + Type::Tuple(types) => { + self.string.push('('); + for (index, typ) in types.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(typ); + } + self.string.push(')'); + } + Type::Struct(struct_type, generics) => { + let struct_type = struct_type.borrow(); + + let current_module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + + // Check if the struct type is already imported/visible in this module + let per_ns = current_module_data.find_name(&struct_type.name); + if let Some((module_def_id, _, _)) = per_ns.types { + if module_def_id == ModuleDefId::TypeId(struct_type.id) { + self.string.push_str(&struct_type.name.0.contents); + self.append_generics(generics); + return; + } + } + + let parent_module_id = struct_type.id.parent_module_id(self.def_maps); + let current_module_parent_id = current_module_data + .parent + .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); + + let relative_path = relative_module_id_path( + parent_module_id, + &self.module_id, + current_module_parent_id, + self.interner, + ); + + if !relative_path.is_empty() { + self.string.push_str(&relative_path); + self.string.push_str("::"); + } + self.string.push_str(&struct_type.name.0.contents); + self.append_generics(generics); + } + Type::Alias(type_alias, generics) => { + let type_alias = type_alias.borrow(); + + let current_module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + + // Check if the alias type is already imported/visible in this module + let per_ns = current_module_data.find_name(&type_alias.name); + if let Some((module_def_id, _, _)) = per_ns.types { + if module_def_id == ModuleDefId::TypeAliasId(type_alias.id) { + self.string.push_str(&type_alias.name.0.contents); + self.append_generics(generics); + return; + } + } + + let parent_module_id = + self.interner.reference_module(ReferenceId::Alias(type_alias.id)).unwrap(); + + let current_module_parent_id = current_module_data + .parent + .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); + + let relative_path = relative_module_id_path( + *parent_module_id, + &self.module_id, + current_module_parent_id, + self.interner, + ); + + if !relative_path.is_empty() { + self.string.push_str(&relative_path); + self.string.push_str("::"); + } + self.string.push_str(&type_alias.name.0.contents); + self.append_generics(generics); + } + Type::TraitAsType(trait_id, _, trait_generics) => { + let trait_ = self.interner.get_trait(*trait_id); + + let current_module_data = + &self.def_maps[&self.module_id.krate].modules()[self.module_id.local_id.0]; + + // Check if the trait type is already imported/visible in this module + let per_ns = current_module_data.find_name(&trait_.name); + if let Some((module_def_id, _, _)) = per_ns.types { + if module_def_id == ModuleDefId::TraitId(*trait_id) { + self.string.push_str(&trait_.name.0.contents); + self.append_trait_generics(trait_generics); + return; + } + } + + let parent_module_id = + self.interner.reference_module(ReferenceId::Trait(*trait_id)).unwrap(); + + let current_module_parent_id = current_module_data + .parent + .map(|parent| ModuleId { krate: self.module_id.krate, local_id: parent }); + + let relative_path = relative_module_id_path( + *parent_module_id, + &self.module_id, + current_module_parent_id, + self.interner, + ); + + if !relative_path.is_empty() { + self.string.push_str(&relative_path); + self.string.push_str("::"); + } + self.string.push_str(&trait_.name.0.contents); + self.append_trait_generics(trait_generics); + } + Type::TypeVariable(typevar) => { + if typevar.id() == self.trait_.self_type_typevar.id() { + self.string.push_str("Self"); + return; + } + + let generics = &self.trait_.generics; + if let Some(index) = + generics.iter().position(|generic| generic.type_var.id() == typevar.id()) + { + if let Some(typ) = self.noir_trait_impl.trait_generics.ordered_args.get(index) { + self.string.push_str(&typ.to_string()); + return; + } + } + + for associated_type in &self.trait_.associated_types { + if typevar.id() == associated_type.type_var.id() { + self.string.push_str("Self::"); + self.string.push_str(&associated_type.name); + return; + } + } + + for generic in &self.func_meta.direct_generics { + if typevar.id() == generic.type_var.id() { + self.string.push_str(&generic.name); + return; + } + } + + self.string.push_str("error"); + } + Type::NamedGeneric(typevar, _name) => { + self.append_type(&Type::TypeVariable(typevar.clone())); + } + Type::Function(args, ret, env, unconstrained) => { + if *unconstrained { + self.string.push_str("unconstrained "); + } + self.string.push_str("fn"); + + if let Type::Unit = **env { + } else { + self.string.push('['); + self.append_type(env); + self.string.push(']'); + } + + self.string.push('('); + for (index, arg) in args.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(arg); + } + self.string.push(')'); + + if let Type::Unit = **ret { + } else { + self.string.push_str(" -> "); + self.append_type(ret); + } + } + Type::MutableReference(typ) => { + self.string.push_str("&mut "); + self.append_type(typ); + } + Type::Forall(_, _) => { + panic!("Shouldn't get a Type::Forall"); + } + Type::InfixExpr(left, op, right) => { + self.append_type(left); + self.string.push(' '); + self.string.push_str(&op.to_string()); + self.string.push(' '); + self.append_type(right); + } + Type::CheckedCast { to, .. } => self.append_type(to), + Type::Constant(..) + | Type::Integer(_, _) + | Type::Bool + | Type::String(_) + | Type::FmtString(_, _) + | Type::Unit + | Type::Quoted(_) + | Type::Error => self.string.push_str(&typ.to_string()), + } + } + + fn append_generics(&mut self, generics: &[Type]) { + if generics.is_empty() { + return; + } + + self.string.push('<'); + for (index, typ) in generics.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(typ); + } + self.string.push('>'); + } + + fn append_trait_generics(&mut self, generics: &TraitGenerics) { + if generics.named.is_empty() && generics.ordered.is_empty() { + return; + } + + let mut index = 0; + + self.string.push('<'); + for generic in &generics.ordered { + if index > 0 { + self.string.push_str(", "); + } + self.append_type(generic); + index += 1; + } + for named_type in &generics.named { + if index > 0 { + self.string.push_str(", "); + } + self.string.push_str(&named_type.name.0.contents); + self.string.push_str(" = "); + self.append_type(&named_type.typ); + index += 1; + } + self.string.push('>'); + } + + fn append_resolved_generics(&mut self, generics: &[ResolvedGeneric]) { + if generics.is_empty() { + return; + } + + self.string.push('<'); + for (index, generic) in self.func_meta.direct_generics.iter().enumerate() { + if index > 0 { + self.string.push_str(", "); + } + self.append_resolved_generic(generic); + } + self.string.push('>'); + } + + fn append_resolved_generic(&mut self, generic: &ResolvedGeneric) { + match &generic.kind() { + Kind::Any | Kind::Normal | Kind::Integer | Kind::IntegerOrField => { + self.string.push_str(&generic.name); + } + Kind::Numeric(ref typ) => { + self.string.push_str("let "); + self.string.push_str(&generic.name); + self.string.push_str(": "); + self.append_type(typ); + } + } + } +} diff --git a/tooling/lsp/src/types.rs b/tooling/lsp/src/types.rs new file mode 100644 index 00000000000..b49377787e8 --- /dev/null +++ b/tooling/lsp/src/types.rs @@ -0,0 +1,246 @@ +use lsp_types::{ + CodeActionOptions, CompletionOptions, DeclarationCapability, DefinitionOptions, + DocumentSymbolOptions, HoverOptions, InlayHintOptions, OneOf, ReferencesOptions, RenameOptions, + SignatureHelpOptions, TypeDefinitionProviderCapability, +}; +use noirc_frontend::graph::CrateName; +use serde::{Deserialize, Serialize}; + +// Re-providing lsp_types that we don't need to override +pub(crate) use lsp_types::{ + CodeLens, CodeLensOptions, CodeLensParams, Command, Diagnostic, DiagnosticSeverity, + DidChangeConfigurationParams, DidChangeTextDocumentParams, DidCloseTextDocumentParams, + DidOpenTextDocumentParams, DidSaveTextDocumentParams, InitializeParams, InitializedParams, + Position, PublishDiagnosticsParams, Range, ServerInfo, TextDocumentSyncCapability, Url, +}; + +pub(crate) mod request { + use lsp_types::{request::Request, InitializeParams}; + + use super::{ + InitializeResult, NargoTestRunParams, NargoTestRunResult, NargoTestsParams, + NargoTestsResult, + }; + + // Re-providing lsp_types that we don't need to override + pub(crate) use lsp_types::request::{ + CodeLensRequest as CodeLens, Formatting, GotoDeclaration, GotoDefinition, + GotoTypeDefinition, Shutdown, + }; + + #[derive(Debug)] + pub(crate) struct Initialize; + impl Request for Initialize { + type Params = InitializeParams; + type Result = InitializeResult; + const METHOD: &'static str = "initialize"; + } + + #[derive(Debug)] + pub(crate) struct NargoTestRun; + impl Request for NargoTestRun { + type Params = NargoTestRunParams; + type Result = NargoTestRunResult; + const METHOD: &'static str = "nargo/tests/run"; + } + + #[derive(Debug)] + pub(crate) struct NargoTests; + impl Request for NargoTests { + type Params = NargoTestsParams; + type Result = NargoTestsResult; + const METHOD: &'static str = "nargo/tests"; + } +} + +pub(crate) mod notification { + use lsp_types::notification::Notification; + + use super::NargoPackageTests; + + // Re-providing lsp_types that we don't need to override + pub(crate) use lsp_types::notification::{ + DidChangeConfiguration, DidChangeTextDocument, DidCloseTextDocument, DidOpenTextDocument, + DidSaveTextDocument, Exit, Initialized, + }; + + pub(crate) struct NargoUpdateTests; + impl Notification for NargoUpdateTests { + type Params = NargoPackageTests; + const METHOD: &'static str = "nargo/tests/update"; + } +} + +#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct NargoTestsOptions { + /// Tests can be requested from the server. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) fetch: Option, + + /// Tests runs can be requested from the server. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) run: Option, + + /// The server will send notifications to update tests. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) update: Option, +} + +#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct NargoCapability { + /// The server will provide various features related to testing within Nargo. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) tests: Option, +} + +#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct ServerCapabilities { + /// Defines how text documents are synced. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) text_document_sync: Option, + + /// The server provides go to declaration support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) declaration_provider: Option, + + /// The server provides goto definition support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) definition_provider: Option>, + + /// The server provides goto type definition support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) type_definition_provider: Option, + + /// The server provides code lens. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) code_lens_provider: Option, + + /// The server provides document formatting. + pub(crate) document_formatting_provider: bool, + + /// The server handles and provides custom nargo messages. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) nargo: Option, + + /// The server provides rename support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) rename_provider: Option>, + + /// The server provides references support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) references_provider: Option>, + + /// The server provides hover support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) hover_provider: Option>, + + /// The server provides inlay hints support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) inlay_hint_provider: Option>, + + /// The server provides document symbol support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) document_symbol_provider: Option>, + + /// The server provides completion support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) completion_provider: Option>, + + /// The server provides signature help support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) signature_help_provider: Option>, + + /// The server provides code action support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) code_action_provider: Option>, +} + +#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct InitializeResult { + /// The capabilities the language server provides. + pub(crate) capabilities: ServerCapabilities, + + /// Information about the server. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) server_info: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(try_from = "String", into = "String")] +pub(crate) struct NargoTestId { + package: CrateName, + fully_qualified_path: String, +} + +impl TryFrom for NargoTestId { + type Error = String; + + fn try_from(value: String) -> Result { + if let Some((crate_name, function_name)) = value.split_once('/') { + let crate_name = crate_name.parse()?; + Ok(Self { package: crate_name, fully_qualified_path: function_name.to_string() }) + } else { + Err("NargoTestId should be serialized as package_name/fully_qualified_path".to_string()) + } + } +} + +impl From for String { + fn from(value: NargoTestId) -> Self { + format!("{}/{}", value.package, value.fully_qualified_path) + } +} + +impl NargoTestId { + pub(crate) fn new(crate_name: CrateName, function_name: String) -> Self { + Self { package: crate_name, fully_qualified_path: function_name } + } + + pub(crate) fn crate_name(&self) -> &CrateName { + &self.package + } + + pub(crate) fn function_name(&self) -> &String { + &self.fully_qualified_path + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub(crate) struct NargoTest { + pub(crate) id: NargoTestId, + /// Fully-qualified path to the test within the crate + pub(crate) label: String, + pub(crate) range: Range, + pub(crate) uri: Url, +} + +#[derive(Debug, Serialize, Deserialize)] +pub(crate) struct NargoPackageTests { + pub(crate) package: String, + pub(crate) tests: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +pub(crate) struct NargoTestsParams {} + +pub(crate) type NargoTestsResult = Option>; + +#[derive(Debug, Serialize, Deserialize)] +pub(crate) struct NargoTestRunParams { + pub(crate) id: NargoTestId, +} + +#[derive(Debug, Serialize, Deserialize)] +pub(crate) struct NargoTestRunResult { + pub(crate) id: NargoTestId, + pub(crate) result: String, + pub(crate) message: Option, +} + +pub(crate) type CodeLensResult = Option>; +pub(crate) type GotoDefinitionResult = Option; +pub(crate) type GotoDeclarationResult = Option; diff --git a/tooling/lsp/src/use_segment_positions.rs b/tooling/lsp/src/use_segment_positions.rs new file mode 100644 index 00000000000..2cd406ee773 --- /dev/null +++ b/tooling/lsp/src/use_segment_positions.rs @@ -0,0 +1,339 @@ +use std::collections::HashMap; + +use fm::{FileId, FileMap}; +use lsp_types::{Position, Range, TextEdit}; +use noirc_errors::Span; +use noirc_frontend::ast::{PathKind, UseTree, UseTreeKind}; + +use crate::requests::to_lsp_location; + +/// The position of a segment in a `use` statement. +/// We use this to determine how an auto-import should be inserted. +#[derive(Debug, Default, Copy, Clone)] +pub(crate) enum UseSegmentPosition { + /// The segment either doesn't exist in the source code or there are multiple segments. + /// In this case auto-import will add a new use statement. + #[default] + NoneOrMultiple, + /// The segment is the last one in the `use` statement (or nested use statement): + /// + /// use foo::bar; + /// ^^^ + /// + /// Auto-import will transform it to this: + /// + /// use foo::bar::{self, baz}; + Last { span: Span }, + /// The segment happens before another simple (ident) segment: + /// + /// use foo::bar::qux; + /// ^^^ + /// + /// Auto-import will transform it to this: + /// + /// use foo::bar::{qux, baz}; + BeforeSegment { segment_span_until_end: Span }, + /// The segment happens before a list: + /// + /// use foo::bar::{qux, another}; + /// + /// Auto-import will transform it to this: + /// + /// use foo::bar::{qux, another, baz}; + BeforeList { first_entry_span: Span, list_is_empty: bool }, +} + +/// Remembers where each segment in a `use` statement is located. +/// The key is the full segment, so for `use foo::bar::baz` we'll have three +/// segments: `foo`, `foo::bar` and `foo::bar::baz`, where the span is just +/// for the last identifier (`foo`, `bar` and `baz` in the previous example). +#[derive(Default)] +pub(crate) struct UseSegmentPositions { + use_segment_positions: HashMap, +} + +impl UseSegmentPositions { + pub(crate) fn add(&mut self, use_tree: &UseTree) { + self.gather_use_tree_segments(use_tree, String::new()); + } + + /// Given a full path like `foo::bar::baz`, returns the first non-"NoneOrMultiple" segment position + /// trying each successive parent, together with the name after the parent. + /// + /// For example, first we'll check if `foo::bar` has a single position. If not, we'll try with `foo`. + pub(crate) fn get(&self, full_path: &str) -> (UseSegmentPosition, String) { + // Build a parent path to know in which full segment we need to add this import + let mut segments: Vec<_> = full_path.split("::").collect(); + let mut name = segments.pop().unwrap().to_string(); + let mut parent_path = segments.join("::"); + + loop { + let use_segment_position = + self.use_segment_positions.get(&parent_path).cloned().unwrap_or_default(); + + if let UseSegmentPosition::NoneOrMultiple = use_segment_position { + if let Some(next_name) = segments.pop() { + name = format!("{next_name}::{name}"); + parent_path = segments.join("::"); + } else { + return (UseSegmentPosition::NoneOrMultiple, String::new()); + } + } else { + return (use_segment_position, name); + } + } + } + + fn gather_use_tree_segments(&mut self, use_tree: &UseTree, mut prefix: String) { + let kind_string = match use_tree.prefix.kind { + PathKind::Crate => Some("crate".to_string()), + PathKind::Super => Some("super".to_string()), + PathKind::Dep | PathKind::Plain => None, + }; + if let Some(kind_string) = kind_string { + if let Some(segment) = use_tree.prefix.segments.first() { + self.insert_use_segment_position( + kind_string, + UseSegmentPosition::BeforeSegment { + segment_span_until_end: Span::from( + segment.ident.span().start()..use_tree.span.end() - 1, + ), + }, + ); + } else { + self.insert_use_segment_position_before_use_tree_kind(use_tree, kind_string); + } + } + + let prefix_segments_len = use_tree.prefix.segments.len(); + for (index, segment) in use_tree.prefix.segments.iter().enumerate() { + let ident = &segment.ident; + if !prefix.is_empty() { + prefix.push_str("::"); + }; + prefix.push_str(&ident.0.contents); + + if index < prefix_segments_len - 1 { + self.insert_use_segment_position( + prefix.clone(), + UseSegmentPosition::BeforeSegment { + segment_span_until_end: Span::from( + use_tree.prefix.segments[index + 1].ident.span().start() + ..use_tree.span.end() - 1, + ), + }, + ); + } else { + self.insert_use_segment_position_before_use_tree_kind(use_tree, prefix.clone()); + } + } + + match &use_tree.kind { + UseTreeKind::Path(ident, alias) => { + if !prefix.is_empty() { + prefix.push_str("::"); + } + prefix.push_str(&ident.0.contents); + + if alias.is_none() { + self.insert_use_segment_position( + prefix, + UseSegmentPosition::Last { span: ident.span() }, + ); + } else { + self.insert_use_segment_position(prefix, UseSegmentPosition::NoneOrMultiple); + } + } + UseTreeKind::List(use_trees) => { + for use_tree in use_trees { + self.gather_use_tree_segments(use_tree, prefix.clone()); + } + } + } + } + + fn insert_use_segment_position_before_use_tree_kind( + &mut self, + use_tree: &UseTree, + prefix: String, + ) { + match &use_tree.kind { + UseTreeKind::Path(ident, _alias) => { + self.insert_use_segment_position( + prefix, + UseSegmentPosition::BeforeSegment { + segment_span_until_end: Span::from( + ident.span().start()..use_tree.span.end() - 1, + ), + }, + ); + } + UseTreeKind::List(use_trees) => { + if let Some(first_use_tree) = use_trees.first() { + self.insert_use_segment_position( + prefix, + UseSegmentPosition::BeforeList { + first_entry_span: first_use_tree.prefix.span(), + list_is_empty: false, + }, + ); + } else { + self.insert_use_segment_position( + prefix, + UseSegmentPosition::BeforeList { + first_entry_span: Span::from( + use_tree.span.end() - 1..use_tree.span.end() - 1, + ), + list_is_empty: true, + }, + ); + } + } + } + } + + fn insert_use_segment_position(&mut self, segment: String, position: UseSegmentPosition) { + match self.use_segment_positions.entry(segment) { + std::collections::hash_map::Entry::Vacant(e) => { + e.insert(position); + } + std::collections::hash_map::Entry::Occupied(mut e) => { + e.insert(UseSegmentPosition::NoneOrMultiple); + } + } + } +} + +pub(crate) struct UseCompletionItemAdditionTextEditsRequest<'a> { + /// The full path of the use statement to insert + pub(crate) full_path: &'a str, + pub(crate) files: &'a FileMap, + pub(crate) file: FileId, + /// All of the current source lines + pub(crate) lines: &'a Vec<&'a str>, + /// How many nested `mod` we are in deep + pub(crate) nesting: usize, + /// The line where an auto_import must be inserted + pub(crate) auto_import_line: usize, +} + +/// Returns the text edits needed to add an auto-import for a given full path. +pub(crate) fn use_completion_item_additional_text_edits( + request: UseCompletionItemAdditionTextEditsRequest, + positions: &UseSegmentPositions, +) -> Vec { + let (use_segment_position, name) = positions.get(request.full_path); + match use_segment_position { + UseSegmentPosition::NoneOrMultiple => { + // The parent path either isn't in any use statement, or it exists in multiple + // use statements. In either case we'll add a new use statement. + + new_use_completion_item_additional_text_edits(request) + } + UseSegmentPosition::Last { span } => { + // We have + // + // use foo::bar; + // ^^^ -> span + // + // and we want to transform it to: + // + // use foo::bar::{self, baz}; + // ^^^^^^^^^^^^^ + // + // So we need one text edit: + // 1. insert "::{self, baz}" right after the span + if let Some(lsp_location) = to_lsp_location(request.files, request.file, span) { + let range = lsp_location.range; + vec![TextEdit { + new_text: format!("::{{self, {}}}", name), + range: Range { start: range.end, end: range.end }, + }] + } else { + new_use_completion_item_additional_text_edits(request) + } + } + UseSegmentPosition::BeforeSegment { segment_span_until_end } => { + // Go past the end + let segment_span_until_end = + Span::from(segment_span_until_end.start()..segment_span_until_end.end() + 1); + + // We have + // + // use foo::bar::{one, two}; + // ^^^^^^^^^^^^^^^ -> segment_span_until_end + // + // and we want to transform it to: + // + // use foo::{bar::{one, two}, baz}; + // ^ ^^^^^^ + // + // So we need two text edits: + // 1. insert "{" right before the segment span + // 2. insert ", baz}" right after the segment span + if let Some(lsp_location) = + to_lsp_location(request.files, request.file, segment_span_until_end) + { + let range = lsp_location.range; + vec![ + TextEdit { + new_text: "{".to_string(), + range: Range { start: range.start, end: range.start }, + }, + TextEdit { + new_text: format!(", {}}}", name), + range: Range { start: range.end, end: range.end }, + }, + ] + } else { + new_use_completion_item_additional_text_edits(request) + } + } + UseSegmentPosition::BeforeList { first_entry_span, list_is_empty } => { + // We have + // + // use foo::bar::{one, two}; + // ^^^ -> first_entry_span + // + // and we want to transform it to: + // + // use foo::bar::{baz, one, two}; + // ^^^^ + // + // So we need one text edit: + // 1. insert "baz, " right before the first entry span + if let Some(lsp_location) = + to_lsp_location(request.files, request.file, first_entry_span) + { + let range = lsp_location.range; + vec![TextEdit { + new_text: if list_is_empty { name } else { format!("{}, ", name) }, + range: Range { start: range.start, end: range.start }, + }] + } else { + new_use_completion_item_additional_text_edits(request) + } + } + } +} + +fn new_use_completion_item_additional_text_edits( + request: UseCompletionItemAdditionTextEditsRequest, +) -> Vec { + let line = request.auto_import_line as u32; + let character = 0; + let indent = " ".repeat(request.nesting * 4); + let mut newlines = "\n"; + + // If the line we are inserting into is not an empty line, insert an extra line to make some room + if let Some(line_text) = request.lines.get(line as usize) { + if !line_text.trim().is_empty() { + newlines = "\n\n"; + } + } + + vec![TextEdit { + range: Range { start: Position { line, character }, end: Position { line, character } }, + new_text: format!("{}use {};{}", indent, request.full_path, newlines), + }] +} diff --git a/tooling/lsp/src/utils.rs b/tooling/lsp/src/utils.rs new file mode 100644 index 00000000000..96db1f7bfa2 --- /dev/null +++ b/tooling/lsp/src/utils.rs @@ -0,0 +1,59 @@ +// These functions are copied from the codespan_lsp crate, except that they never panic +// (the library will sometimes panic, so functions returning Result are not always accurate) + +use fm::codespan_files::Files; +use fm::{FileId, FileMap}; + +pub(crate) fn range_to_byte_span( + files: &FileMap, + file_id: FileId, + range: &lsp_types::Range, +) -> Option> { + Some( + position_to_byte_index(files, file_id, &range.start)? + ..position_to_byte_index(files, file_id, &range.end)?, + ) +} + +pub(crate) fn position_to_byte_index( + files: &FileMap, + file_id: FileId, + position: &lsp_types::Position, +) -> Option { + let Ok(source) = files.source(file_id) else { + return None; + }; + + let Ok(line_span) = files.line_range(file_id, position.line as usize) else { + return None; + }; + let line_str = source.get(line_span.clone())?; + + let byte_offset = character_to_line_offset(line_str, position.character)?; + + Some(line_span.start + byte_offset) +} + +pub(crate) fn character_to_line_offset(line: &str, character: u32) -> Option { + let line_len = line.len(); + let mut character_offset = 0; + + let mut chars = line.chars(); + while let Some(ch) = chars.next() { + if character_offset == character { + let chars_off = chars.as_str().len(); + let ch_off = ch.len_utf8(); + + return Some(line_len - chars_off - ch_off); + } + + character_offset += ch.len_utf16() as u32; + } + + // Handle positions after the last character on the line + if character_offset == character { + Some(line_len) + } else { + None + } +} diff --git a/tooling/lsp/src/visibility.rs b/tooling/lsp/src/visibility.rs new file mode 100644 index 00000000000..6724a0ba505 --- /dev/null +++ b/tooling/lsp/src/visibility.rs @@ -0,0 +1,55 @@ +use std::collections::BTreeMap; + +use noirc_frontend::{ + ast::ItemVisibility, + graph::CrateId, + hir::{ + def_map::{CrateDefMap, ModuleDefId, ModuleId}, + resolution::visibility::item_in_module_is_visible, + }, + node_interner::NodeInterner, +}; + +use crate::modules::get_parent_module; + +/// Returns true if the given ModuleDefId is visible from the current module, given its visibility. +/// This will in turn check if the ModuleDefId parent modules are visible from the current module. +/// If `defining_module` is Some, it will be considered as the parent of the item to check +/// (this is the case when the item is re-exported with `pub use` or similar). +pub(super) fn module_def_id_is_visible( + module_def_id: ModuleDefId, + current_module_id: ModuleId, + mut visibility: ItemVisibility, + mut defining_module: Option, + interner: &NodeInterner, + def_maps: &BTreeMap, +) -> bool { + // First find out which module we need to check. + // If a module is trying to be referenced, it's that module. Otherwise it's the module that contains the item. + let mut target_module_id = if let ModuleDefId::ModuleId(module_id) = module_def_id { + Some(module_id) + } else { + std::mem::take(&mut defining_module).or_else(|| get_parent_module(interner, module_def_id)) + }; + + // Then check if it's visible, and upwards + while let Some(module_id) = target_module_id { + if !item_in_module_is_visible(def_maps, current_module_id, module_id, visibility) { + return false; + } + + target_module_id = std::mem::take(&mut defining_module).or_else(|| { + let module_data = &def_maps[&module_id.krate].modules()[module_id.local_id.0]; + let parent_local_id = module_data.parent; + parent_local_id.map(|local_id| ModuleId { krate: module_id.krate, local_id }) + }); + + // This is a bit strange, but the visibility is always that of the item inside another module, + // so the visibility we update here is for the next loop check. + visibility = interner + .try_module_attributes(&module_id) + .map_or(ItemVisibility::Public, |attributes| attributes.visibility); + } + + true +} diff --git a/tooling/lsp/test_programs/document_symbol/Nargo.toml b/tooling/lsp/test_programs/document_symbol/Nargo.toml new file mode 100644 index 00000000000..367b145f045 --- /dev/null +++ b/tooling/lsp/test_programs/document_symbol/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "document_symbol" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/document_symbol/src/main.nr b/tooling/lsp/test_programs/document_symbol/src/main.nr new file mode 100644 index 00000000000..a88a6a21e1f --- /dev/null +++ b/tooling/lsp/test_programs/document_symbol/src/main.nr @@ -0,0 +1,28 @@ +fn foo(_x: i32) { + let _ = 1; +} + +struct SomeStruct { + field: i32, +} + +impl SomeStruct { + fn new() -> SomeStruct { + SomeStruct { field: 0 } + } +} + +trait SomeTrait { + fn some_method(x: U); +} + +impl SomeTrait for SomeStruct { + fn some_method(_x: i32) { + } +} + +mod submodule { + global SOME_GLOBAL = 1; +} + +impl i32 {} diff --git a/tooling/lsp/test_programs/go_to_definition/Nargo.toml b/tooling/lsp/test_programs/go_to_definition/Nargo.toml new file mode 100644 index 00000000000..96fc9cab39a --- /dev/null +++ b/tooling/lsp/test_programs/go_to_definition/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "go_to_definition" +type = "bin" +authors = [""] + +[dependencies] +dependency = { path = "dependency" } \ No newline at end of file diff --git a/tooling/lsp/test_programs/go_to_definition/dependency/Nargo.toml b/tooling/lsp/test_programs/go_to_definition/dependency/Nargo.toml new file mode 100644 index 00000000000..2e471678a44 --- /dev/null +++ b/tooling/lsp/test_programs/go_to_definition/dependency/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "dependency" +type = "lib" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/tooling/lsp/test_programs/go_to_definition/dependency/src/lib.nr b/tooling/lsp/test_programs/go_to_definition/dependency/src/lib.nr new file mode 100644 index 00000000000..6833f391999 --- /dev/null +++ b/tooling/lsp/test_programs/go_to_definition/dependency/src/lib.nr @@ -0,0 +1 @@ +pub fn something() {} diff --git a/tooling/lsp/test_programs/go_to_definition/src/bar.nr b/tooling/lsp/test_programs/go_to_definition/src/bar.nr new file mode 100644 index 00000000000..6792022dc10 --- /dev/null +++ b/tooling/lsp/test_programs/go_to_definition/src/bar.nr @@ -0,0 +1,5 @@ +pub fn baz() {} + +mod inline { + pub fn qux() {} +} diff --git a/tooling/lsp/test_programs/go_to_definition/src/main.nr b/tooling/lsp/test_programs/go_to_definition/src/main.nr new file mode 100644 index 00000000000..cb04fe04eaa --- /dev/null +++ b/tooling/lsp/test_programs/go_to_definition/src/main.nr @@ -0,0 +1,37 @@ +mod foo { + pub fn another_function() -> Field { + 3 + 4 + } +} + +use foo::another_function; +use foo::another_function as aliased_function; + +mod bar; + +fn some_function() -> Field { + 1 + 2 +} + +fn main() { + let _ = another_function(); + bar::baz(); + bar::inline::qux(); +} + +struct Foo { + +} + +trait Trait { + +} + +use dependency::something; + +#[attr] +pub fn foo() {} + +comptime fn attr(_: FunctionDefinition) -> Quoted { + quote { pub fn hello() {} } +} \ No newline at end of file diff --git a/tooling/lsp/test_programs/inlay_hints/Nargo.toml b/tooling/lsp/test_programs/inlay_hints/Nargo.toml new file mode 100644 index 00000000000..89f8eda14be --- /dev/null +++ b/tooling/lsp/test_programs/inlay_hints/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "inlay_hints" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/inlay_hints/src/main.nr b/tooling/lsp/test_programs/inlay_hints/src/main.nr new file mode 100644 index 00000000000..46a6d3bc558 --- /dev/null +++ b/tooling/lsp/test_programs/inlay_hints/src/main.nr @@ -0,0 +1,122 @@ +fn main() { + let var = 0; +} + +struct Foo { + +} + +fn make_foo() -> Foo { + Foo {} +} + +fn foo() { + let foo = make_foo(); +} + +fn test_for() { + for i in 0..10 {} +} + +global var = 0; + +fn test_fn(one: i32, two: i32) {} + +fn call_test_fn() { + test_fn(1, 2); // Should show parameter names +} + +struct SomeStruct { + one: i32, +} + +impl SomeStruct { + fn some_method(self, one: i32) {} +} + +fn call_method() { + let s = SomeStruct { one: 1 }; + s.some_method(1); // Should show parameter names +} + +fn call_where_name_matches() { + let one = 1; + let two = 2; + test_fn(one, two); // Should not show parameter names (names match) +} + +fn call_where_member_name_matches() { + let s = SomeStruct { one: 1 }; + let two = 2; + test_fn(s.one, two); // Should not show parameter names (member name matches) +} + +fn one() -> i32 { + 1 +} + +fn call_where_call_matches_name() { + let two = 2; + test_fn(one(), two); // Should not show parameter names (call name matches) +} + +fn with_arg(arg: i32) {} + +fn call_with_arg() { + let x = 1; + with_arg(x); // Should not show parameter names ("arg" is a suffix of "with_arg") +} + +fn with_underscore(_x: i32) {} + +fn call_with_underscore() { + with_underscore(1); // Should not show parameter names (param name starts with underscore) +} + +fn one_arg_with_one_char(x: i32) {} + +fn call_one_arg_with_one_char() { + one_arg_with_one_char(1); // Should not show parameter names (only one param and it's a single letter) +} + +fn one_arg_with_obvious_name(other: i32) {} + +fn call_one_arg_with_obvious_name() { + one_arg_with_obvious_name(1); // Should not show parameter names (only one param and it's an obvious name) +} + +fn yet_another_function(name: i32) {} + +fn call_yet_another_function() { + let some_name = 1; + yet_another_function(some_name) // Should not show parameter names ("name" is a suffix of "some_name") +} + +fn struct_member_hint() { + let SomeStruct { one } = SomeStruct { one: 1 }; +} + +fn some_map(x: T, f: fn(T) -> U) -> U { + f(x) +} + +fn hint_on_lambda_parameter() { + let value: i32 = 1; + let _: i32 = some_map(value, |x| x + 1); +} + +trait SomeTrait { + +} + +impl SomeTrait for SomeStruct { + +} + +mod some_module { + +} + +contract some_contract { + +} diff --git a/tooling/lsp/test_programs/local_variable/Nargo.toml b/tooling/lsp/test_programs/local_variable/Nargo.toml new file mode 100644 index 00000000000..df881fb5f4d --- /dev/null +++ b/tooling/lsp/test_programs/local_variable/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "local_variable" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/local_variable/src/main.nr b/tooling/lsp/test_programs/local_variable/src/main.nr new file mode 100644 index 00000000000..e41cbed085f --- /dev/null +++ b/tooling/lsp/test_programs/local_variable/src/main.nr @@ -0,0 +1,5 @@ +fn main() { + let mut some_var = 1; + some_var = 2; + let _ = some_var; +} diff --git a/tooling/lsp/test_programs/rename/Nargo.toml b/tooling/lsp/test_programs/rename/Nargo.toml new file mode 100644 index 00000000000..2d5b6415dc9 --- /dev/null +++ b/tooling/lsp/test_programs/rename/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/rename/src/main.nr b/tooling/lsp/test_programs/rename/src/main.nr new file mode 100644 index 00000000000..4c28249582e --- /dev/null +++ b/tooling/lsp/test_programs/rename/src/main.nr @@ -0,0 +1,22 @@ +fn some_function() -> Field { + 1 + 2 +} + +fn another_function() -> Field { + 3 + 4 +} + +fn main() { + let _ = another_function(); + + let _ = 1; + + let _ = another_function(); +} + + +mod foo { + fn yet_another_function() -> Field { + crate::another_function() + } +} \ No newline at end of file diff --git a/tooling/lsp/test_programs/rename_function/Nargo.toml b/tooling/lsp/test_programs/rename_function/Nargo.toml new file mode 100644 index 00000000000..529fde06128 --- /dev/null +++ b/tooling/lsp/test_programs/rename_function/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_function" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/rename_function/src/main.nr b/tooling/lsp/test_programs/rename_function/src/main.nr new file mode 100644 index 00000000000..e77b50c0b26 --- /dev/null +++ b/tooling/lsp/test_programs/rename_function/src/main.nr @@ -0,0 +1,40 @@ +fn some_function() -> Field { + 1 + 2 +} + +fn another_function() -> Field { + 3 + 4 +} + +fn main() { + let _ = another_function(); + + let _ = 1; + + let _ = another_function(); +} + +mod foo { + fn some_other_function() -> Field { + crate::another_function() + } +} + +use foo::some_other_function as bar; + +fn x() { + bar(); +} + +struct SomeStruct { + +} + +impl SomeStruct { + fn some_method(self) {} +} + +fn y() { + let some_struct = SomeStruct {}; + some_struct.some_method(); +} diff --git a/tooling/lsp/test_programs/rename_function_use/Nargo.toml b/tooling/lsp/test_programs/rename_function_use/Nargo.toml new file mode 100644 index 00000000000..e2eb25886bf --- /dev/null +++ b/tooling/lsp/test_programs/rename_function_use/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_function_use" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/rename_function_use/src/main.nr b/tooling/lsp/test_programs/rename_function_use/src/main.nr new file mode 100644 index 00000000000..e1b7c98ab0f --- /dev/null +++ b/tooling/lsp/test_programs/rename_function_use/src/main.nr @@ -0,0 +1,12 @@ +mod foo { + pub fn some_function() -> Field { + 1 + 2 + } +} + +use foo::some_function; + +fn main() { + let _ = some_function(); +} + diff --git a/tooling/lsp/test_programs/rename_global/Nargo.toml b/tooling/lsp/test_programs/rename_global/Nargo.toml new file mode 100644 index 00000000000..350c6fe5506 --- /dev/null +++ b/tooling/lsp/test_programs/rename_global/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_global" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/rename_global/src/main.nr b/tooling/lsp/test_programs/rename_global/src/main.nr new file mode 100644 index 00000000000..3ae8cf4bfc3 --- /dev/null +++ b/tooling/lsp/test_programs/rename_global/src/main.nr @@ -0,0 +1,22 @@ +mod foo { + global FOO = 1; +} + +use foo::FOO; + +fn main() { + let _ = foo::FOO; + let _ = FOO; + let _: [Field; FOO] = [1]; +} + +trait WithNumber { + +} + +struct Some { +} + +impl WithNumber for Some { + +} diff --git a/tooling/lsp/test_programs/rename_qualified/Nargo.toml b/tooling/lsp/test_programs/rename_qualified/Nargo.toml new file mode 100644 index 00000000000..7de13ef6b34 --- /dev/null +++ b/tooling/lsp/test_programs/rename_qualified/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_qualified" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/rename_qualified/src/main.nr b/tooling/lsp/test_programs/rename_qualified/src/main.nr new file mode 100644 index 00000000000..f1b77796210 --- /dev/null +++ b/tooling/lsp/test_programs/rename_qualified/src/main.nr @@ -0,0 +1,9 @@ +fn main() -> pub Field { + foo::bar() +} + +mod foo { + pub fn bar() -> Field { + 1 + } +} diff --git a/tooling/lsp/test_programs/rename_qualified_function/Nargo.toml b/tooling/lsp/test_programs/rename_qualified_function/Nargo.toml new file mode 100644 index 00000000000..c0aaa3ce658 --- /dev/null +++ b/tooling/lsp/test_programs/rename_qualified_function/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_qualified_function" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/rename_qualified_function/src/main.nr b/tooling/lsp/test_programs/rename_qualified_function/src/main.nr new file mode 100644 index 00000000000..f1b77796210 --- /dev/null +++ b/tooling/lsp/test_programs/rename_qualified_function/src/main.nr @@ -0,0 +1,9 @@ +fn main() -> pub Field { + foo::bar() +} + +mod foo { + pub fn bar() -> Field { + 1 + } +} diff --git a/tooling/lsp/test_programs/rename_struct/Nargo.toml b/tooling/lsp/test_programs/rename_struct/Nargo.toml new file mode 100644 index 00000000000..e5822098e58 --- /dev/null +++ b/tooling/lsp/test_programs/rename_struct/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_struct" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/rename_struct/src/main.nr b/tooling/lsp/test_programs/rename_struct/src/main.nr new file mode 100644 index 00000000000..d9da3e75763 --- /dev/null +++ b/tooling/lsp/test_programs/rename_struct/src/main.nr @@ -0,0 +1,31 @@ +mod foo { + mod bar { + struct Foo { + field: Field, + } + + impl Foo { + fn foo() {} + + fn bar(self) {} + + fn baz() -> Self { + Self { field: 1 } + } + } + } +} + +use foo::bar::Foo; + +fn main(x: Field) -> pub Field { + let foo1 = Foo { field: 1 }; + let foo2 = Foo { field: 2 }; + let Foo { field } = foo1; + Foo::foo(); + x +} + +fn foo(foo: Foo) -> Foo { + foo +} diff --git a/tooling/lsp/test_programs/rename_trait/Nargo.toml b/tooling/lsp/test_programs/rename_trait/Nargo.toml new file mode 100644 index 00000000000..a8cc34898bd --- /dev/null +++ b/tooling/lsp/test_programs/rename_trait/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_trait" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/rename_trait/src/main.nr b/tooling/lsp/test_programs/rename_trait/src/main.nr new file mode 100644 index 00000000000..dd0783985a7 --- /dev/null +++ b/tooling/lsp/test_programs/rename_trait/src/main.nr @@ -0,0 +1,21 @@ +mod foo { + mod bar { + trait Foo { + fn foo() {} + } + } +} + +use foo::bar::Foo; + +struct Bar { + +} + +impl Foo for Bar { + +} + +fn main() { + foo::bar::Foo::foo(); +} diff --git a/tooling/lsp/test_programs/rename_type_alias/Nargo.toml b/tooling/lsp/test_programs/rename_type_alias/Nargo.toml new file mode 100644 index 00000000000..1b95727ed8d --- /dev/null +++ b/tooling/lsp/test_programs/rename_type_alias/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_type_alias" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/rename_type_alias/src/main.nr b/tooling/lsp/test_programs/rename_type_alias/src/main.nr new file mode 100644 index 00000000000..2072d9cae87 --- /dev/null +++ b/tooling/lsp/test_programs/rename_type_alias/src/main.nr @@ -0,0 +1,24 @@ +mod foo { + struct Foo { + } + + type Bar = Foo; + + mod bar { + struct Baz { + + } + } +} + +use foo::Foo; +use foo::Bar; +use foo::bar; + +fn main() { + let x: Bar = Foo {}; +} + +fn x(b: Bar) -> Bar { + b +} diff --git a/tooling/lsp/test_programs/struct_member/Nargo.toml b/tooling/lsp/test_programs/struct_member/Nargo.toml new file mode 100644 index 00000000000..5272b9abb68 --- /dev/null +++ b/tooling/lsp/test_programs/struct_member/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "struct_member" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/lsp/test_programs/struct_member/src/main.nr b/tooling/lsp/test_programs/struct_member/src/main.nr new file mode 100644 index 00000000000..3f1bac9df66 --- /dev/null +++ b/tooling/lsp/test_programs/struct_member/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + some_member: Field +} + +fn main() { + let mut foo = Foo { some_member: 1 }; + foo.some_member = 2; + let _ = foo.some_member; + + let Foo { some_member } = foo; + let Foo { some_member: some_var } = foo; +} diff --git a/tooling/lsp/test_programs/workspace/Nargo.toml b/tooling/lsp/test_programs/workspace/Nargo.toml new file mode 100644 index 00000000000..d0a0badc295 --- /dev/null +++ b/tooling/lsp/test_programs/workspace/Nargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["one", "two"] diff --git a/tooling/lsp/test_programs/workspace/one/Nargo.toml b/tooling/lsp/test_programs/workspace/one/Nargo.toml new file mode 100644 index 00000000000..39838d73362 --- /dev/null +++ b/tooling/lsp/test_programs/workspace/one/Nargo.toml @@ -0,0 +1,4 @@ +[package] +name = "one" +authors = [] +type = "lib" diff --git a/tooling/lsp/test_programs/workspace/one/src/lib.nr b/tooling/lsp/test_programs/workspace/one/src/lib.nr new file mode 100644 index 00000000000..61f282fa2a7 --- /dev/null +++ b/tooling/lsp/test_programs/workspace/one/src/lib.nr @@ -0,0 +1,25 @@ +pub fn function_one() {} + +mod subone { + struct SubOneStruct { + some_field: i32, + some_other_field: Field, + } + + impl SubOneStruct { + fn foo(self, x: i32, y: i32) -> Field { + 0 + } + } + + trait SomeTrait { + } + + global some_global = 2; + + type SomeAlias = i32; + + struct GenericStruct { + + } +} diff --git a/tooling/lsp/test_programs/workspace/two/Nargo.toml b/tooling/lsp/test_programs/workspace/two/Nargo.toml new file mode 100644 index 00000000000..26d99b65df1 --- /dev/null +++ b/tooling/lsp/test_programs/workspace/two/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "two" +authors = [] +type = "lib" + +[dependencies] +one = { path = "../one" } \ No newline at end of file diff --git a/tooling/lsp/test_programs/workspace/two/src/lib.nr b/tooling/lsp/test_programs/workspace/two/src/lib.nr new file mode 100644 index 00000000000..d18a663b276 --- /dev/null +++ b/tooling/lsp/test_programs/workspace/two/src/lib.nr @@ -0,0 +1,95 @@ +use one::function_one; + +pub fn function_two() { + function_one() +} + +use one::subone; + +fn use_struct() { + let _ = subone::SubOneStruct { some_field: 0, some_other_field: 2 }; +} + +use one::subone::SomeTrait; + +fn use_global() { + let _ = one::subone::some_global; +} + +fn use_struct_method() { + let s = subone::SubOneStruct { some_field: 0, some_other_field: 2 }; + s.foo(0, 1); +} + +fn use_local_var() { + let regular_var = 0; + let _ = regular_var; + let mut mutable_var = 0; + mutable_var = 1; +} + +fn use_parameter(some_param: i32) { + let _ = some_param; +} + +use one::subone::SomeAlias; + +use std::default::Default; + +fn use_impl_method() { + let _: i32 = Default::default(); +} + +mod other; +use crate::other::other_function; +use other::another_function; + +use one::subone::GenericStruct; + +use std::collections::bounded_vec::BoundedVec; + +fn instantiate_generic() { + let x: BoundedVec = BoundedVec::new(); +} + +#[attr] +pub fn foo() {} + +comptime fn attr(_: FunctionDefinition) -> Quoted { + quote { pub fn hello() {} } +} + +struct Foo {} + +impl Foo { + fn new() -> Self { + Foo {} + } +} + +fn new_foo() -> Foo { + Foo::new() +} + +trait Bar { + fn bar_stuff(self); +} + +impl Bar for Foo { + fn bar_stuff(self) {} +} + +fn bar_stuff() { + let foo = Foo::new(); + foo.bar_stuff(); +} + +trait TraitWithDocs { + /// Some docs + fn foo(); +} + +impl TraitWithDocs for Field { + fn foo() {} +} + diff --git a/tooling/lsp/test_programs/workspace/two/src/other.nr b/tooling/lsp/test_programs/workspace/two/src/other.nr new file mode 100644 index 00000000000..4d2fffcee80 --- /dev/null +++ b/tooling/lsp/test_programs/workspace/two/src/other.nr @@ -0,0 +1,2 @@ +fn other_function() {} +fn another_function() {} diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml new file mode 100644 index 00000000000..4587638d693 --- /dev/null +++ b/tooling/nargo/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "nargo" +description = "Noir's package manager" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[lints] +workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +acvm.workspace = true +fm.workspace = true +noirc_abi.workspace = true +noirc_driver.workspace = true +noirc_errors.workspace = true +noirc_frontend.workspace = true +noirc_printable_type.workspace = true +iter-extended.workspace = true +jsonrpsee.workspace = true +rayon.workspace = true +thiserror.workspace = true +tracing.workspace = true +serde.workspace = true +serde_json.workspace = true +walkdir = "2.5.0" +noir_fuzzer = { workspace = true } +proptest = { workspace = true } + +# Some dependencies are optional so we can compile to Wasm. +tokio = { workspace = true, optional = true } +rand = { workspace = true, optional = true } + +[dev-dependencies] +jsonrpsee = { workspace = true, features = ["server"] } + +[features] +default = [] + +# Execution currently uses HTTP based Oracle resolvers; does not compile to Wasm. +rpc = ["jsonrpsee/http-client", "jsonrpsee/macros", "tokio/rt", "rand"] diff --git a/tooling/nargo/src/constants.rs b/tooling/nargo/src/constants.rs new file mode 100644 index 00000000000..1048d86fcd7 --- /dev/null +++ b/tooling/nargo/src/constants.rs @@ -0,0 +1,23 @@ +// Directories +/// The directory for the `nargo contract` command output +pub const CONTRACT_DIR: &str = "contract"; +/// The directory to store serialized circuit proofs. +pub const PROOFS_DIR: &str = "proofs"; +/// The directory to store Noir source files +pub const SRC_DIR: &str = "src"; +/// The directory to store circuits' serialized ACIR representations. +pub const TARGET_DIR: &str = "target"; +/// The directory to store serialized ACIR representations of exported library functions. +pub const EXPORT_DIR: &str = "export"; + +// Files +/// The file from which Nargo pulls prover inputs +pub const PROVER_INPUT_FILE: &str = "Prover"; +/// The package definition file for a Noir project. +pub const PKG_FILE: &str = "Nargo.toml"; + +// Extensions +/// The extension for files containing circuit proofs. +pub const PROOF_EXT: &str = "proof"; +/// The extension for files containing proof witnesses. +pub const WITNESS_EXT: &str = "gz"; diff --git a/tooling/nargo/src/errors.rs b/tooling/nargo/src/errors.rs new file mode 100644 index 00000000000..00c411bf7e4 --- /dev/null +++ b/tooling/nargo/src/errors.rs @@ -0,0 +1,246 @@ +use std::collections::BTreeMap; + +use acvm::{ + acir::circuit::{ + brillig::BrilligFunctionId, ErrorSelector, OpcodeLocation, RawAssertionPayload, + ResolvedAssertionPayload, ResolvedOpcodeLocation, + }, + pwg::{ErrorLocation, OpcodeResolutionError}, + AcirField, FieldElement, +}; +use noirc_abi::{display_abi_error, Abi, AbiErrorType}; +use noirc_errors::{ + debug_info::DebugInfo, reporter::ReportedErrors, CustomDiagnostic, FileDiagnostic, +}; + +pub use noirc_errors::Location; + +use noirc_driver::CrateName; +use thiserror::Error; + +use crate::foreign_calls::ForeignCallError; + +/// Errors covering situations where a package cannot be compiled. +#[derive(Debug, Error)] +pub enum CompileError { + #[error("Package `{0}` has type `lib` but only `bin` types can be compiled")] + LibraryCrate(CrateName), + + #[error("Package `{0}` is expected to have a `main` function but it does not")] + MissingMainFunction(CrateName), + + /// Errors encountered while compiling the Noir program. + /// These errors are already written to stderr. + #[error("Aborting due to {} previous error{}", .0.error_count, if .0.error_count == 1 { "" } else { "s" })] + ReportedErrors(ReportedErrors), +} +impl From for CompileError { + fn from(errors: ReportedErrors) -> Self { + Self::ReportedErrors(errors) + } +} + +#[derive(Debug, Error)] +pub enum NargoError { + /// Error while compiling Noir into ACIR. + #[error("Failed to compile circuit")] + CompilationError, + + /// ACIR circuit execution error + #[error(transparent)] + ExecutionError(#[from] ExecutionError), + + /// Oracle handling error + #[error(transparent)] + ForeignCallError(#[from] ForeignCallError), +} + +impl NargoError { + /// Extracts the user defined failure message from the ExecutionError + /// If one exists. + /// + /// 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, + error_types: &BTreeMap, + ) -> Option { + match self { + NargoError::ExecutionError(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::BlackBoxFunctionFailed(_, reason) => { + Some(reason.to_string()) + } + _ => None, + }, + }, + NargoError::ForeignCallError(error) => Some(error.to_string()), + _ => None, + } + } +} + +#[derive(Debug, Error)] +pub enum ExecutionError { + #[error("Failed assertion")] + AssertionFailed( + ResolvedAssertionPayload, + Vec, + Option, + ), + + #[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], +) -> Option> { + let mut opcode_locations = match error { + 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::InvalidInputBitSize { 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(_) => acir_call_stack.clone(), + }, + _ => None, + }?; + + // 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; + } + } + + let brillig_function_id = match error { + ExecutionError::SolvingError( + OpcodeResolutionError::BrilligFunctionFailed { function_id, .. }, + _, + ) => Some(*function_id), + ExecutionError::AssertionFailed(_, _, function_id) => *function_id, + _ => None, + }; + + Some( + opcode_locations + .iter() + .flat_map(|resolved_location| { + debug[resolved_location.acir_function_index] + .opcode_location(&resolved_location.opcode_location) + .unwrap_or_else(|| { + if let (Some(brillig_function_id), Some(brillig_location)) = ( + brillig_function_id, + &resolved_location.opcode_location.to_brillig_location(), + ) { + let brillig_locations = debug[resolved_location.acir_function_index] + .brillig_locations + .get(&brillig_function_id); + brillig_locations + .unwrap() + .get(brillig_location) + .cloned() + .unwrap_or_default() + } else { + vec![] + } + }) + }) + .collect(), + ) +} + +fn extract_message_from_error( + error_types: &BTreeMap, + nargo_err: &NargoError, +) -> 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); + let error = CustomDiagnostic::simple_error(message, String::new(), location.span); + Some(error.with_call_stack(source_locations).in_file(location.file)) +} diff --git a/tooling/nargo/src/foreign_calls/default.rs b/tooling/nargo/src/foreign_calls/default.rs new file mode 100644 index 00000000000..19928e89563 --- /dev/null +++ b/tooling/nargo/src/foreign_calls/default.rs @@ -0,0 +1,152 @@ +use acvm::AcirField; +use serde::{Deserialize, Serialize}; + +use crate::PrintOutput; + +use super::{ + layers::{self, Either, Layer, Layering}, + mocker::{DisabledMockForeignCallExecutor, MockForeignCallExecutor}, + print::PrintForeignCallExecutor, + ForeignCallExecutor, +}; + +#[cfg(feature = "rpc")] +use super::rpc::RPCForeignCallExecutor; + +/// A builder for [DefaultForeignCallLayers] where we can enable fields based on feature flags, +/// which is easier than providing different overrides for a `new` method. +pub struct DefaultForeignCallBuilder<'a> { + pub output: PrintOutput<'a>, + pub enable_mocks: bool, + + #[cfg(feature = "rpc")] + pub resolver_url: Option, + + #[cfg(feature = "rpc")] + pub root_path: Option, + + #[cfg(feature = "rpc")] + pub package_name: Option, +} + +impl<'a> Default for DefaultForeignCallBuilder<'a> { + fn default() -> Self { + Self { + output: PrintOutput::default(), + enable_mocks: true, + + #[cfg(feature = "rpc")] + resolver_url: None, + + #[cfg(feature = "rpc")] + root_path: None, + + #[cfg(feature = "rpc")] + package_name: None, + } + } +} + +impl<'a> DefaultForeignCallBuilder<'a> { + /// Override the output. + pub fn with_output(mut self, output: PrintOutput<'a>) -> Self { + self.output = output; + self + } + + /// Enable or disable mocks. + pub fn with_mocks(mut self, enabled: bool) -> Self { + self.enable_mocks = enabled; + self + } + + /// Compose the executor layers with [layers::Empty] as the default handler. + pub fn build(self) -> DefaultForeignCallLayers<'a, layers::Empty, F> + where + F: AcirField + Serialize + for<'de> Deserialize<'de> + 'a, + { + self.build_with_base(layers::Empty) + } + + /// Compose the executor layers with `base` as the default handler. + pub fn build_with_base(self, base: B) -> DefaultForeignCallLayers<'a, B, F> + where + F: AcirField + Serialize + for<'de> Deserialize<'de> + 'a, + B: ForeignCallExecutor + 'a, + { + let executor = { + #[cfg(feature = "rpc")] + { + use rand::Rng; + + base.add_layer(self.resolver_url.map(|resolver_url| { + let id = rand::thread_rng().gen(); + RPCForeignCallExecutor::new( + &resolver_url, + id, + self.root_path, + self.package_name, + ) + })) + } + #[cfg(not(feature = "rpc"))] + { + base + } + }; + + executor + .add_layer(if self.enable_mocks { + Either::Left(MockForeignCallExecutor::default()) + } else { + Either::Right(DisabledMockForeignCallExecutor) + }) + .add_layer(PrintForeignCallExecutor::new(self.output)) + } +} + +/// Facilitate static typing of layers on a base layer, so inner layers can be accessed. +#[cfg(feature = "rpc")] +pub type DefaultForeignCallLayers<'a, B, F> = Layer< + PrintForeignCallExecutor<'a>, + Layer< + Either, DisabledMockForeignCallExecutor>, + Layer, B>, + >, +>; +#[cfg(not(feature = "rpc"))] +pub type DefaultForeignCallLayers<'a, B, F> = Layer< + PrintForeignCallExecutor<'a>, + Layer, DisabledMockForeignCallExecutor>, B>, +>; + +/// Convenience constructor for code that used to create the executor this way. +#[cfg(feature = "rpc")] +pub struct DefaultForeignCallExecutor; + +/// Convenience constructors for the RPC case. Non-RPC versions are not provided +/// because once a crate opts into this within the workspace, everyone gets it +/// even if they don't want to. For the non-RPC case we can nudge people to +/// use `DefaultForeignCallBuilder` which is easier to keep flexible. +#[cfg(feature = "rpc")] +impl DefaultForeignCallExecutor { + #[allow(clippy::new_ret_no_self)] + pub fn new<'a, F>( + output: PrintOutput<'a>, + resolver_url: Option<&str>, + root_path: Option, + package_name: Option, + ) -> impl ForeignCallExecutor + 'a + where + F: AcirField + Serialize + for<'de> Deserialize<'de> + 'a, + { + DefaultForeignCallBuilder { + output, + enable_mocks: true, + resolver_url: resolver_url.map(|s| s.to_string()), + root_path, + package_name, + } + .build() + } +} diff --git a/tooling/nargo/src/foreign_calls/layers.rs b/tooling/nargo/src/foreign_calls/layers.rs new file mode 100644 index 00000000000..83145cacb44 --- /dev/null +++ b/tooling/nargo/src/foreign_calls/layers.rs @@ -0,0 +1,162 @@ +use acvm::{acir::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo, AcirField}; + +use super::{ForeignCallError, ForeignCallExecutor}; + +/// Returns an empty result when called. +/// +/// If all executors have no handler for the given foreign call 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. +pub struct Empty; + +impl ForeignCallExecutor for Empty { + fn execute( + &mut self, + _foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + Ok(ForeignCallResult::default()) + } +} + +/// Returns `NoHandler` for every call. +pub struct Unhandled; + +impl ForeignCallExecutor for Unhandled { + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + Err(ForeignCallError::NoHandler(foreign_call.function.clone())) + } +} + +/// Forwards to the inner executor if its own handler doesn't handle the call. +pub struct Layer { + pub handler: H, + pub inner: I, +} + +impl ForeignCallExecutor for Layer +where + H: ForeignCallExecutor, + I: ForeignCallExecutor, +{ + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + match self.handler.execute(foreign_call) { + Err(ForeignCallError::NoHandler(_)) => self.inner.execute(foreign_call), + handled => handled, + } + } +} + +impl Layer { + /// Create a layer from two handlers + pub fn new(handler: H, inner: I) -> Self { + Self { handler, inner } + } +} + +impl Layer { + /// Create a layer from a handler. + /// If the handler doesn't handle a call, a default empty response is returned. + pub fn or_empty(handler: H) -> Self { + Self { handler, inner: Empty } + } +} + +impl Layer { + /// Create a layer from a handler. + /// If the handler doesn't handle a call, `NoHandler` error is returned. + pub fn or_unhandled(handler: H) -> Self { + Self { handler, inner: Unhandled } + } +} + +impl Layer { + /// A base layer that doesn't handle anything. + pub fn unhandled() -> Self { + Self { handler: Unhandled, inner: Unhandled } + } +} + +impl Layer { + /// Add another layer on top of this one. + pub fn add_layer(self, handler: J) -> Layer { + Layer::new(handler, self) + } + + pub fn handler(&self) -> &H { + &self.handler + } + + pub fn inner(&self) -> &I { + &self.inner + } +} + +/// Compose handlers. +pub trait Layering { + /// Layer an executor on top of this one. + /// The `other` executor will be called first. + fn add_layer(self, other: L) -> Layer + where + Self: Sized + ForeignCallExecutor, + L: ForeignCallExecutor; +} + +impl Layering for T { + fn add_layer(self, other: L) -> Layer + where + T: Sized + ForeignCallExecutor, + L: ForeignCallExecutor, + { + Layer::new(other, self) + } +} + +/// A case where we can have either this or that type of handler. +pub enum Either { + Left(L), + Right(R), +} + +impl ForeignCallExecutor for Either +where + L: ForeignCallExecutor, + R: ForeignCallExecutor, +{ + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + match self { + Either::Left(left) => left.execute(foreign_call), + Either::Right(right) => right.execute(foreign_call), + } + } +} + +/// Support disabling a layer by making it optional. +/// This way we can still have a known static type for a composition, +/// because layers are always added, potentially wrapped in an `Option`. +impl ForeignCallExecutor for Option +where + H: ForeignCallExecutor, +{ + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + match self { + Some(handler) => handler.execute(foreign_call), + None => Err(ForeignCallError::NoHandler(foreign_call.function.clone())), + } + } +} diff --git a/tooling/nargo/src/foreign_calls/mocker.rs b/tooling/nargo/src/foreign_calls/mocker.rs new file mode 100644 index 00000000000..41fac610052 --- /dev/null +++ b/tooling/nargo/src/foreign_calls/mocker.rs @@ -0,0 +1,201 @@ +use acvm::{ + acir::brillig::{ForeignCallParam, ForeignCallResult}, + pwg::ForeignCallWaitInfo, + AcirField, +}; +use noirc_abi::decode_string_value; + +use super::{ForeignCall, ForeignCallError, ForeignCallExecutor}; + +/// This struct represents an oracle mock. It can be used for testing programs that use oracles. +#[derive(Debug, PartialEq, Eq, Clone)] +struct MockedCall { + /// The id of the mock, used to update or remove it + id: usize, + /// The oracle it's mocking + name: String, + /// Optionally match the parameters + 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, + /// How many times should this mock be called before it is removed + times_left: Option, +} + +impl MockedCall { + fn new(id: usize, name: String) -> Self { + Self { + id, + name, + params: None, + last_called_params: None, + result: ForeignCallResult { values: vec![] }, + times_left: None, + } + } +} + +impl MockedCall { + fn matches(&self, name: &str, params: &[ForeignCallParam]) -> bool { + self.name == name && (self.params.is_none() || self.params.as_deref() == Some(params)) + } +} + +#[derive(Debug, Default)] +pub struct MockForeignCallExecutor { + /// Mocks have unique ids used to identify them in Noir, allowing to update or remove them. + last_mock_id: usize, + /// The registered mocks + mocked_responses: Vec>, +} + +impl MockForeignCallExecutor { + fn extract_mock_id( + foreign_call_inputs: &[ForeignCallParam], + ) -> Result<(usize, &[ForeignCallParam]), ForeignCallError> { + let (id, params) = + foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?; + 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(&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.fields().to_vec(); + decode_string_value(&fields) + } +} + +impl ForeignCallExecutor for MockForeignCallExecutor +where + F: AcirField, +{ + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + let foreign_call_name = foreign_call.function.as_str(); + match ForeignCall::lookup(foreign_call_name) { + Some(ForeignCall::CreateMock) => { + let mock_oracle_name = Self::parse_string(&foreign_call.inputs[0]); + assert!(ForeignCall::lookup(&mock_oracle_name).is_none()); + let id = self.last_mock_id; + self.mocked_responses.push(MockedCall::new(id, mock_oracle_name)); + self.last_mock_id += 1; + + Ok(F::from(id).into()) + } + Some(ForeignCall::SetMockParams) => { + let (id, params) = Self::extract_mock_id(&foreign_call.inputs)?; + self.find_mock_by_id_mut(id) + .unwrap_or_else(|| panic!("Unknown mock id {}", id)) + .params = Some(params.to_vec()); + + 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_mut(id) + .unwrap_or_else(|| panic!("Unknown mock id {}", id)) + .result = ForeignCallResult { values: params.to_vec() }; + + Ok(ForeignCallResult::default()) + } + Some(ForeignCall::SetMockTimes) => { + let (id, params) = Self::extract_mock_id(&foreign_call.inputs)?; + let times = + params[0].unwrap_field().try_to_u64().expect("Invalid bit size of times"); + + self.find_mock_by_id_mut(id) + .unwrap_or_else(|| panic!("Unknown mock id {}", id)) + .times_left = Some(times); + + 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()) + } + _ => { + let mock_response_position = self + .mocked_responses + .iter() + .position(|response| response.matches(foreign_call_name, &foreign_call.inputs)); + + 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()); + + 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); + } + } + + Ok(result.into()) + } else { + Err(ForeignCallError::NoHandler(foreign_call_name.to_string())) + } + } + } + } +} + +/// Handler that panics if any of the mock functions are called. +pub struct DisabledMockForeignCallExecutor; + +impl ForeignCallExecutor for DisabledMockForeignCallExecutor { + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + let foreign_call_name = foreign_call.function.as_str(); + if let Some( + ForeignCall::CreateMock + | ForeignCall::SetMockParams + | ForeignCall::GetMockLastParams + | ForeignCall::SetMockReturns + | ForeignCall::SetMockTimes + | ForeignCall::ClearMock, + ) = ForeignCall::lookup(foreign_call_name) + { + // Returning an error instead of panicking so this can be tested. + return Err(ForeignCallError::Disabled(foreign_call.function.to_string())); + } + Err(ForeignCallError::NoHandler(foreign_call.function.clone())) + } +} diff --git a/tooling/nargo/src/foreign_calls/mod.rs b/tooling/nargo/src/foreign_calls/mod.rs new file mode 100644 index 00000000000..f17a97cecd4 --- /dev/null +++ b/tooling/nargo/src/foreign_calls/mod.rs @@ -0,0 +1,86 @@ +use acvm::{acir::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo}; +use thiserror::Error; + +pub mod layers; +pub mod mocker; +pub mod print; + +pub mod default; +#[cfg(feature = "rpc")] +pub mod rpc; +pub use default::DefaultForeignCallBuilder; +#[cfg(feature = "rpc")] +pub use default::DefaultForeignCallExecutor; + +pub trait ForeignCallExecutor { + fn execute( + &mut self, + 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, + CreateMock, + SetMockParams, + GetMockLastParams, + SetMockReturns, + SetMockTimes, + ClearMock, +} + +impl std::fmt::Display for ForeignCall { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name()) + } +} + +impl ForeignCall { + pub(crate) fn name(&self) -> &'static str { + match self { + ForeignCall::Print => "print", + 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", + } + } + + pub(crate) fn lookup(op_name: &str) -> Option { + match op_name { + "print" => Some(ForeignCall::Print), + "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), + _ => None, + } + } +} + +#[derive(Debug, Error)] +pub enum ForeignCallError { + #[error("Attempted to call disabled foreign call `{0}`")] + Disabled(String), + + #[error("No handler could be found for foreign call `{0}`")] + NoHandler(String), + + #[error("Foreign call inputs needed for execution are missing")] + MissingForeignCallInputs, + + #[error("Could not parse PrintableType argument. {0}")] + ParsingError(#[from] serde_json::Error), + + #[error("Failed calling external resolver. {0}")] + ExternalResolverError(#[from] jsonrpsee::core::client::Error), + + #[error("Assert message resolved after an unsatisfied constrain. {0}")] + ResolvedAssertMessage(String), +} diff --git a/tooling/nargo/src/foreign_calls/print.rs b/tooling/nargo/src/foreign_calls/print.rs new file mode 100644 index 00000000000..fb5621da942 --- /dev/null +++ b/tooling/nargo/src/foreign_calls/print.rs @@ -0,0 +1,133 @@ +use acvm::{ + acir::brillig::{ForeignCallParam, ForeignCallResult}, + pwg::ForeignCallWaitInfo, + AcirField, +}; +use noirc_abi::{decode_printable_value, decode_string_value}; +use noirc_printable_type::{PrintableType, PrintableValueDisplay}; + +use super::{ForeignCall, ForeignCallError, ForeignCallExecutor}; + +#[derive(Debug, Default)] +pub enum PrintOutput<'a> { + #[default] + None, + Stdout, + String(&'a mut String), +} + +#[derive(Debug, Default)] +pub struct PrintForeignCallExecutor<'a> { + output: PrintOutput<'a>, +} + +impl<'a> PrintForeignCallExecutor<'a> { + pub fn new(output: PrintOutput<'a>) -> Self { + Self { output } + } +} + +impl ForeignCallExecutor for PrintForeignCallExecutor<'_> { + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + let foreign_call_name = foreign_call.function.as_str(); + match ForeignCall::lookup(foreign_call_name) { + Some(ForeignCall::Print) => { + 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; + + let display_values: PrintableValueDisplay = + try_from_params(foreign_call_inputs)?; + let display_string = + format!("{display_values}{}", if skip_newline { "" } else { "\n" }); + + match &mut self.output { + PrintOutput::None => (), + PrintOutput::Stdout => print!("{display_string}"), + PrintOutput::String(string) => { + string.push_str(&display_string); + } + } + + Ok(ForeignCallResult::default()) + } + _ => Err(ForeignCallError::NoHandler(foreign_call_name.to_string())), + } + } +} + +fn try_from_params( + foreign_call_inputs: &[ForeignCallParam], +) -> Result, ForeignCallError> { + let (is_fmt_str, foreign_call_inputs) = + foreign_call_inputs.split_last().ok_or(ForeignCallError::MissingForeignCallInputs)?; + + if is_fmt_str.unwrap_field().is_one() { + convert_fmt_string_inputs(foreign_call_inputs) + } else { + convert_string_inputs(foreign_call_inputs) + } +} + +fn convert_string_inputs( + foreign_call_inputs: &[ForeignCallParam], +) -> Result, ForeignCallError> { + // Fetch the PrintableType from the foreign call input + // The remaining input values should hold what is to be printed + let (printable_type_as_values, input_values) = + foreign_call_inputs.split_last().ok_or(ForeignCallError::MissingForeignCallInputs)?; + 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| param.fields()); + + let value = decode_printable_value(&mut input_values_as_fields, &printable_type); + + Ok(PrintableValueDisplay::Plain(value, printable_type)) +} + +fn convert_fmt_string_inputs( + foreign_call_inputs: &[ForeignCallParam], +) -> Result, ForeignCallError> { + let (message, input_and_printable_types) = + foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?; + + 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 + .split_first() + .ok_or(ForeignCallError::MissingForeignCallInputs)?; + + let mut output = Vec::new(); + 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| 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_printable_value(&mut input_iter, &printable_type); + + output.push((value, printable_type)); + } + + Ok(PrintableValueDisplay::FmtString(message_as_string, output)) +} + +fn fetch_printable_type( + printable_type: &ForeignCallParam, +) -> Result { + 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)?; + + Ok(printable_type) +} diff --git a/tooling/nargo/src/foreign_calls/rpc.rs b/tooling/nargo/src/foreign_calls/rpc.rs new file mode 100644 index 00000000000..89a748b6c45 --- /dev/null +++ b/tooling/nargo/src/foreign_calls/rpc.rs @@ -0,0 +1,283 @@ +use std::path::PathBuf; + +use acvm::{acir::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo, AcirField}; +use jsonrpsee::{ + core::client::ClientT, + http_client::{HttpClient, HttpClientBuilder}, + rpc_params, +}; +use serde::{Deserialize, Serialize}; + +use super::{ForeignCallError, ForeignCallExecutor}; + +#[derive(Debug)] +pub struct RPCForeignCallExecutor { + /// A randomly generated id for this `DefaultForeignCallExecutor`. + /// + /// This is used so that a single `external_resolver` can distinguish between requests from multiple + /// instantiations of `DefaultForeignCallExecutor`. + id: u64, + /// JSON RPC client to resolve foreign calls + external_resolver: HttpClient, + /// Root path to the program or workspace in execution. + root_path: Option, + /// Name of the package in execution + package_name: Option, + /// Runtime to execute asynchronous tasks on. + /// See [bridging](https://tokio.rs/tokio/topics/bridging). + runtime: tokio::runtime::Runtime, +} + +#[derive(Debug, Serialize, Deserialize)] +struct ResolveForeignCallRequest { + /// A session ID which allows the external RPC server to link this foreign call request to other foreign calls + /// for the same program execution. + /// + /// This is intended to allow a single RPC server to maintain state related to multiple program executions being + /// performed in parallel. + session_id: u64, + + /// The foreign call which the external RPC server is to provide a response for. + #[serde(flatten)] + function_call: ForeignCallWaitInfo, + + /// Root path to the program or workspace in execution. + #[serde(skip_serializing_if = "Option::is_none")] + root_path: Option, + + /// Name of the package in execution + #[serde(skip_serializing_if = "Option::is_none")] + package_name: Option, +} + +type ResolveForeignCallResult = Result, ForeignCallError>; + +impl RPCForeignCallExecutor { + pub fn new( + resolver_url: &str, + id: u64, + root_path: Option, + package_name: Option, + ) -> Self { + let mut client_builder = HttpClientBuilder::new(); + + 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); + client_builder = client_builder.request_timeout(timeout_duration); + }; + + let oracle_resolver = + client_builder.build(resolver_url).expect("Invalid oracle resolver URL"); + + // Opcodes are executed in the `ProgramExecutor::execute_circuit` one by one in a loop, + // we don't need a concurrent thread pool. + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_time() + .enable_io() + .build() + .expect("failed to build tokio runtime"); + + RPCForeignCallExecutor { + external_resolver: oracle_resolver, + id, + root_path, + package_name, + runtime, + } + } +} + +impl ForeignCallExecutor for RPCForeignCallExecutor +where + F: AcirField + Serialize + for<'a> Deserialize<'a>, +{ + /// Execute an async call blocking the current thread. + /// This method cannot be called from inside a `tokio` runtime, for that to work + /// we need to offload the execution into a different thread; see the tests. + fn execute(&mut self, foreign_call: &ForeignCallWaitInfo) -> ResolveForeignCallResult { + let encoded_params = rpc_params!(ResolveForeignCallRequest { + session_id: self.id, + function_call: foreign_call.clone(), + root_path: self.root_path.clone().map(|path| path.to_str().unwrap().to_string()), + package_name: self.package_name.clone(), + }); + + let parsed_response = self.runtime.block_on(async { + self.external_resolver.request("resolve_foreign_call", encoded_params).await + })?; + + Ok(parsed_response) + } +} + +#[cfg(test)] +mod tests { + use acvm::{ + acir::brillig::ForeignCallParam, brillig_vm::brillig::ForeignCallResult, + pwg::ForeignCallWaitInfo, FieldElement, + }; + use jsonrpsee::proc_macros::rpc; + use jsonrpsee::server::Server; + use jsonrpsee::types::ErrorObjectOwned; + use tokio::sync::{mpsc, oneshot}; + + use super::{ + ForeignCallExecutor, RPCForeignCallExecutor, ResolveForeignCallRequest, + ResolveForeignCallResult, + }; + + #[rpc(server)] + trait OracleResolver { + #[method(name = "resolve_foreign_call")] + fn resolve_foreign_call( + &self, + req: ResolveForeignCallRequest, + ) -> Result, ErrorObjectOwned>; + } + + struct OracleResolverImpl; + + impl OracleResolverImpl { + fn echo(&self, param: ForeignCallParam) -> ForeignCallResult { + vec![param].into() + } + + fn sum(&self, array: ForeignCallParam) -> ForeignCallResult { + let mut res: FieldElement = 0_usize.into(); + + for value in array.fields() { + res += value; + } + + res.into() + } + } + + impl OracleResolverServer for OracleResolverImpl { + fn resolve_foreign_call( + &self, + req: ResolveForeignCallRequest, + ) -> Result, ErrorObjectOwned> { + let response = match req.function_call.function.as_str() { + "sum" => self.sum(req.function_call.inputs[0].clone()), + "echo" => self.echo(req.function_call.inputs[0].clone()), + "id" => FieldElement::from(req.session_id as u128).into(), + _ => panic!("unexpected foreign call"), + }; + Ok(response) + } + } + + /// The test client send its request and a response channel. + type RPCForeignCallClientRequest = ( + ForeignCallWaitInfo, + oneshot::Sender>, + ); + + /// Async client used in the tests. + #[derive(Clone)] + struct RPCForeignCallClient { + tx: mpsc::UnboundedSender, + } + + impl RPCForeignCallExecutor { + /// Spawn and run the executor in the background until all clients are closed. + fn run(mut self) -> RPCForeignCallClient { + let (tx, mut rx) = mpsc::unbounded_channel::(); + let handle = tokio::task::spawn_blocking(move || { + while let Some((req, tx)) = rx.blocking_recv() { + let res = self.execute(&req); + let _ = tx.send(res); + } + }); + // The task will finish when the client goes out of scope. + drop(handle); + RPCForeignCallClient { tx } + } + } + + impl RPCForeignCallClient { + /// Asynchronously execute a foreign call. + async fn execute( + &self, + req: &ForeignCallWaitInfo, + ) -> ResolveForeignCallResult { + let (tx, rx) = oneshot::channel(); + self.tx.send((req.clone(), tx)).expect("failed to send to executor"); + rx.await.expect("failed to receive from executor") + } + } + + /// Start running the Oracle server or a random port, returning the listen URL. + async fn build_oracle_server() -> std::io::Result { + // Choosing port 0 results in a random port being assigned. + let server = Server::builder().build("127.0.0.1:0").await?; + let addr = server.local_addr()?; + let handle = server.start(OracleResolverImpl.into_rpc()); + let url = format!("http://{}", addr); + // In this test we don't care about doing shutdown so let's it run forever. + tokio::spawn(handle.stopped()); + Ok(url) + } + + #[tokio::test] + async fn test_oracle_resolver_echo() { + let url = build_oracle_server().await.unwrap(); + + let executor = RPCForeignCallExecutor::new(&url, 1, None, None).run(); + + let foreign_call: ForeignCallWaitInfo = ForeignCallWaitInfo { + function: "echo".to_string(), + inputs: vec![ForeignCallParam::Single(1_u128.into())], + }; + + let result = executor.execute(&foreign_call).await; + assert_eq!(result.unwrap(), ForeignCallResult { values: foreign_call.inputs }); + } + + #[tokio::test] + async fn test_oracle_resolver_sum() { + let url = build_oracle_server().await.unwrap(); + + let executor = RPCForeignCallExecutor::new(&url, 2, None, None).run(); + + let foreign_call: ForeignCallWaitInfo = ForeignCallWaitInfo { + function: "sum".to_string(), + inputs: vec![ForeignCallParam::Array(vec![1_usize.into(), 2_usize.into()])], + }; + + let result = executor.execute(&foreign_call).await; + assert_eq!(result.unwrap(), FieldElement::from(3_usize).into()); + } + + #[tokio::test] + async fn foreign_call_executor_id_is_persistent() { + let url = build_oracle_server().await.unwrap(); + + let executor = RPCForeignCallExecutor::new(&url, 3, None, None).run(); + + let foreign_call: ForeignCallWaitInfo = + ForeignCallWaitInfo { function: "id".to_string(), inputs: Vec::new() }; + + let result_1 = executor.execute(&foreign_call).await.unwrap(); + let result_2 = executor.execute(&foreign_call).await.unwrap(); + assert_eq!(result_1, result_2); + } + + #[tokio::test] + async fn oracle_resolver_rpc_can_distinguish_executors() { + let url = build_oracle_server().await.unwrap(); + + let executor_1 = RPCForeignCallExecutor::new(&url, 4, None, None).run(); + let executor_2 = RPCForeignCallExecutor::new(&url, 5, None, None).run(); + + let foreign_call: ForeignCallWaitInfo = + ForeignCallWaitInfo { function: "id".to_string(), inputs: Vec::new() }; + + let result_1 = executor_1.execute(&foreign_call).await.unwrap(); + let result_2 = executor_2.execute(&foreign_call).await.unwrap(); + assert_ne!(result_1, result_2); + } +} diff --git a/tooling/nargo/src/lib.rs b/tooling/nargo/src/lib.rs new file mode 100644 index 00000000000..30f25356e41 --- /dev/null +++ b/tooling/nargo/src/lib.rs @@ -0,0 +1,188 @@ +#![forbid(unsafe_code)] +#![warn(unused_crate_dependencies, unused_extern_crates)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] + +//! Nargo is the package manager for Noir +//! This name was used because it sounds like `cargo` and +//! Noir Package Manager abbreviated is npm, which is already taken. + +pub mod constants; +pub mod errors; +pub mod foreign_calls; +pub mod ops; +pub mod package; +pub mod workspace; + +pub use self::errors::NargoError; +pub use self::foreign_calls::print::PrintOutput; + +use std::{ + collections::{BTreeMap, HashMap, HashSet}, + path::PathBuf, +}; + +use fm::{FileManager, FILE_EXTENSION}; +use noirc_driver::{add_dep, prepare_crate, prepare_dependency}; +use noirc_frontend::{ + graph::{CrateId, CrateName}, + hir::{def_map::parse_file, Context, ParsedFiles}, +}; +use package::{Dependency, Package}; +use rayon::prelude::*; +use walkdir::WalkDir; + +pub fn prepare_dependencies( + context: &mut Context, + parent_crate: CrateId, + dependencies: &BTreeMap, +) { + for (dep_name, dep) in dependencies.iter() { + match dep { + Dependency::Remote { package } | Dependency::Local { package } => { + let crate_id = prepare_dependency(context, &package.entry_path); + add_dep(context, parent_crate, crate_id, dep_name.clone()); + prepare_dependencies(context, crate_id, &package.dependencies); + } + } + } +} + +pub fn insert_all_files_for_workspace_into_file_manager( + workspace: &workspace::Workspace, + file_manager: &mut FileManager, +) { + insert_all_files_for_workspace_into_file_manager_with_overrides( + workspace, + file_manager, + &HashMap::new(), + ); +} + +pub fn insert_all_files_for_workspace_into_file_manager_with_overrides( + workspace: &workspace::Workspace, + file_manager: &mut FileManager, + overrides: &HashMap<&std::path::Path, &str>, +) { + let mut processed_entry_paths = HashSet::new(); + for package in workspace.clone().into_iter() { + insert_all_files_for_package_into_file_manager( + package, + file_manager, + overrides, + &mut processed_entry_paths, + ); + } +} +// We will pre-populate the file manager with all the files in the package +// This is so that we can avoid having to read from disk when we are compiling +// +// This does not require parsing because we are interested in the files under the src directory +// it may turn out that we do not need to include some Noir files that we add to the file +// manager +fn insert_all_files_for_package_into_file_manager( + package: &Package, + file_manager: &mut FileManager, + overrides: &HashMap<&std::path::Path, &str>, + processed_entry_paths: &mut HashSet, +) { + if processed_entry_paths.contains(&package.entry_path) { + return; + } + processed_entry_paths.insert(package.entry_path.clone()); + + // Start off at the entry path and read all files in the parent directory. + let entry_path_parent = package + .entry_path + .parent() + .unwrap_or_else(|| panic!("The entry path is expected to be a single file within a directory and so should have a parent {:?}", package.entry_path)); + + for entry in WalkDir::new(entry_path_parent).sort_by_file_name() { + let Ok(entry) = entry else { + continue; + }; + + if !entry.file_type().is_file() { + continue; + } + + if !entry.path().extension().map_or(false, |ext| ext == FILE_EXTENSION) { + continue; + }; + + let path = entry.into_path(); + + // Avoid reading the source if the file is already there + if file_manager.has_file(&path) { + continue; + } + + let source = if let Some(src) = overrides.get(path.as_path()) { + src.to_string() + } else { + std::fs::read_to_string(path.as_path()) + .unwrap_or_else(|_| panic!("could not read file {:?} into string", path)) + }; + + file_manager.add_file_with_source(path.as_path(), source); + } + + insert_all_files_for_packages_dependencies_into_file_manager( + package, + file_manager, + overrides, + processed_entry_paths, + ); +} + +// Inserts all files for the dependencies of the package into the file manager +// too +fn insert_all_files_for_packages_dependencies_into_file_manager( + package: &Package, + file_manager: &mut FileManager, + overrides: &HashMap<&std::path::Path, &str>, + processed_entry_paths: &mut HashSet, +) { + for (_, dep) in package.dependencies.iter() { + match dep { + Dependency::Local { package } | Dependency::Remote { package } => { + insert_all_files_for_package_into_file_manager( + package, + file_manager, + overrides, + processed_entry_paths, + ); + } + } + } +} + +pub fn parse_all(file_manager: &FileManager) -> ParsedFiles { + file_manager + .as_file_map() + .all_file_ids() + .par_bridge() + .filter(|&&file_id| { + let file_path = file_manager.path(file_id).expect("expected file to exist"); + let file_extension = + file_path.extension().expect("expected all file paths to have an extension"); + file_extension == "nr" + }) + .map(|&file_id| (file_id, parse_file(file_manager, file_id))) + .collect() +} + +#[tracing::instrument(level = "trace", skip_all)] +pub fn prepare_package<'file_manager, 'parsed_files>( + file_manager: &'file_manager FileManager, + parsed_files: &'parsed_files ParsedFiles, + package: &Package, +) -> (Context<'file_manager, 'parsed_files>, CrateId) { + let mut context = Context::from_ref_file_manager(file_manager, parsed_files); + + let crate_id = prepare_crate(&mut context, &package.entry_path); + + prepare_dependencies(&mut context, crate_id, &package.dependencies); + + (context, crate_id) +} diff --git a/tooling/nargo/src/ops/check.rs b/tooling/nargo/src/ops/check.rs new file mode 100644 index 00000000000..f22def8bd91 --- /dev/null +++ b/tooling/nargo/src/ops/check.rs @@ -0,0 +1,22 @@ +use acvm::compiler::CircuitSimulator; +use noirc_driver::{CompiledProgram, ErrorsAndWarnings}; +use noirc_errors::{CustomDiagnostic, FileDiagnostic}; + +/// Run each function through a circuit simulator to check that they are solvable. +#[tracing::instrument(level = "trace", skip_all)] +pub fn check_program(compiled_program: &CompiledProgram) -> Result<(), ErrorsAndWarnings> { + for (i, circuit) in compiled_program.program.functions.iter().enumerate() { + let mut simulator = CircuitSimulator::default(); + if !simulator.check_circuit(circuit) { + let diag = FileDiagnostic { + file_id: fm::FileId::dummy(), + diagnostic: CustomDiagnostic::from_message(&format!( + "Circuit \"{}\" is not solvable", + compiled_program.names[i] + )), + }; + return Err(vec![diag]); + } + } + Ok(()) +} diff --git a/tooling/nargo/src/ops/compile.rs b/tooling/nargo/src/ops/compile.rs new file mode 100644 index 00000000000..8c44bf35243 --- /dev/null +++ b/tooling/nargo/src/ops/compile.rs @@ -0,0 +1,153 @@ +use fm::FileManager; +use noirc_driver::{ + link_to_debug_crate, CompilationResult, CompileOptions, CompiledContract, CompiledProgram, +}; +use noirc_frontend::debug::DebugInstrumenter; +use noirc_frontend::hir::ParsedFiles; + +use crate::errors::CompileError; +use crate::prepare_package; +use crate::{package::Package, workspace::Workspace}; + +use rayon::prelude::*; + +/// Compiles workspace. +/// +/// # Errors +/// +/// This function will return an error if there are any compilations errors reported. +pub fn compile_workspace( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + workspace: &Workspace, + compile_options: &CompileOptions, +) -> CompilationResult<(Vec, Vec)> { + let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace + .into_iter() + .filter(|package| !package.is_library()) + .cloned() + .partition(|package| package.is_binary()); + + // Compile all of the packages in parallel. + let program_results: Vec> = binary_packages + .par_iter() + .map(|package| { + compile_program(file_manager, parsed_files, workspace, package, compile_options, None) + }) + .collect(); + let contract_results: Vec> = contract_packages + .par_iter() + .map(|package| compile_contract(file_manager, parsed_files, package, compile_options)) + .collect(); + + // 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( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + workspace: &Workspace, + package: &Package, + compile_options: &CompileOptions, + cached_program: Option, +) -> CompilationResult { + compile_program_with_debug_instrumenter( + file_manager, + parsed_files, + workspace, + package, + compile_options, + cached_program, + DebugInstrumenter::default(), + ) +} + +#[tracing::instrument(level = "trace", name = "compile_program" skip_all, fields(package = package.name.to_string()))] +pub fn compile_program_with_debug_instrumenter( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + workspace: &Workspace, + package: &Package, + compile_options: &CompileOptions, + cached_program: Option, + debug_instrumenter: DebugInstrumenter, +) -> CompilationResult { + let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package); + link_to_debug_crate(&mut context, crate_id); + context.debug_instrumenter = debug_instrumenter; + context.package_build_path = workspace.package_build_path(package); + + noirc_driver::compile_main(&mut context, crate_id, compile_options, cached_program) +} + +#[tracing::instrument(level = "trace", skip_all, fields(package_name = package.name.to_string()))] +pub fn compile_contract( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + package: &Package, + compile_options: &CompileOptions, +) -> CompilationResult { + let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package); + noirc_driver::compile_contract(&mut context, crate_id, compile_options) +} + +/// 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, + silence_warnings: bool, +) -> Result { + let (t, warnings) = result.map_err(|errors| { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &errors, + deny_warnings, + silence_warnings, + ) + })?; + + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &warnings, + deny_warnings, + silence_warnings, + ); + + Ok(t) +} diff --git a/tooling/nargo/src/ops/execute.rs b/tooling/nargo/src/ops/execute.rs new file mode 100644 index 00000000000..57116ec2efd --- /dev/null +++ b/tooling/nargo/src/ops/execute.rs @@ -0,0 +1,259 @@ +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, ProfilingSamples, ACVM, +}; +use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; +use acvm::{AcirField, BlackBoxFunctionSolver}; + +use crate::errors::ExecutionError; +use crate::foreign_calls::ForeignCallExecutor; +use crate::NargoError; + +struct ProgramExecutor<'a, F, B: BlackBoxFunctionSolver, E: 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 E, + + // 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, + + // Flag that states whether we want to profile the VM. Profiling can add extra + // execution costs so we want to make sure we only trigger it explicitly. + profiling_active: bool, +} + +impl<'a, F: AcirField, B: BlackBoxFunctionSolver, E: ForeignCallExecutor> + ProgramExecutor<'a, F, B, E> +{ + fn new( + functions: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], + blackbox_solver: &'a B, + foreign_call_executor: &'a mut E, + profiling_active: bool, + ) -> Self { + ProgramExecutor { + functions, + unconstrained_functions, + witness_stack: WitnessStack::default(), + blackbox_solver, + foreign_call_executor, + call_stack: Vec::default(), + current_function_index: 0, + profiling_active, + } + } + + fn finalize(self) -> WitnessStack { + self.witness_stack + } + + #[tracing::instrument(level = "trace", skip_all)] + fn execute_circuit( + &mut self, + initial_witness: WitnessMap, + ) -> Result<(WitnessMap, ProfilingSamples), 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, + ); + acvm.with_profiler(self.profiling_active); + + 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), + .. + } + | OpcodeResolutionError::IndexOutOfBounds { + opcode_location: ErrorLocation::Resolved(opcode_location), + .. + } + | OpcodeResolutionError::InvalidInputBitSize { + 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()) + } + 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, + }; + + let brillig_function_id = match &error { + OpcodeResolutionError::BrilligFunctionFailed { function_id, .. } => { + Some(*function_id) + } + _ => None, + }; + + return Err(NargoError::ExecutionError(match assertion_payload { + Some(payload) => ExecutionError::AssertionFailed( + payload, + call_stack.expect("Should have call stack for an assertion failure"), + brillig_function_id, + ), + 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()), + }); + + // 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; + // TODO: Profiling among multiple circuits is not supported + 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.0, call_solved_witness); + } + } + } + // Clear the call stack if we have succeeded in executing the circuit. + // This needs to be done or else all successful ACIR call stacks will also be + // included in a failure case. + self.call_stack.clear(); + + let profiling_samples = acvm.take_profiling_samples(); + Ok((acvm.finalize(), profiling_samples)) + } +} + +pub fn execute_program, E: ForeignCallExecutor>( + program: &Program, + initial_witness: WitnessMap, + blackbox_solver: &B, + foreign_call_executor: &mut E, +) -> Result, NargoError> { + let profiling_active = false; + let (witness_stack, profiling_samples) = execute_program_inner( + program, + initial_witness, + blackbox_solver, + foreign_call_executor, + profiling_active, + )?; + assert!(profiling_samples.is_empty(), "Expected no profiling samples"); + + Ok(witness_stack) +} + +pub fn execute_program_with_profiling< + F: AcirField, + B: BlackBoxFunctionSolver, + E: ForeignCallExecutor, +>( + program: &Program, + initial_witness: WitnessMap, + blackbox_solver: &B, + foreign_call_executor: &mut E, +) -> Result<(WitnessStack, ProfilingSamples), NargoError> { + let profiling_active = true; + execute_program_inner( + program, + initial_witness, + blackbox_solver, + foreign_call_executor, + profiling_active, + ) +} + +#[tracing::instrument(level = "trace", skip_all)] +fn execute_program_inner, E: ForeignCallExecutor>( + program: &Program, + initial_witness: WitnessMap, + blackbox_solver: &B, + foreign_call_executor: &mut E, + profiling_active: bool, +) -> Result<(WitnessStack, ProfilingSamples), NargoError> { + let mut executor = ProgramExecutor::new( + &program.functions, + &program.unconstrained_functions, + blackbox_solver, + foreign_call_executor, + profiling_active, + ); + let (main_witness, profiling_samples) = executor.execute_circuit(initial_witness)?; + executor.witness_stack.push(0, main_witness); + + Ok((executor.finalize(), profiling_samples)) +} diff --git a/tooling/nargo/src/ops/mod.rs b/tooling/nargo/src/ops/mod.rs new file mode 100644 index 00000000000..7a52a829be3 --- /dev/null +++ b/tooling/nargo/src/ops/mod.rs @@ -0,0 +1,17 @@ +pub use self::check::check_program; +pub use self::compile::{ + collect_errors, compile_contract, compile_program, compile_program_with_debug_instrumenter, + compile_workspace, report_errors, +}; +pub use self::optimize::{optimize_contract, optimize_program}; +pub use self::transform::{transform_contract, transform_program}; + +pub use self::execute::{execute_program, execute_program_with_profiling}; +pub use self::test::{run_test, TestStatus}; + +mod check; +mod compile; +mod execute; +mod optimize; +mod test; +mod transform; diff --git a/tooling/nargo/src/ops/optimize.rs b/tooling/nargo/src/ops/optimize.rs new file mode 100644 index 00000000000..07adfb57df4 --- /dev/null +++ b/tooling/nargo/src/ops/optimize.rs @@ -0,0 +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 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| { + 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 new file mode 100644 index 00000000000..a2f94cd61eb --- /dev/null +++ b/tooling/nargo/src/ops/test.rs @@ -0,0 +1,291 @@ +use acvm::{ + acir::{ + brillig::ForeignCallResult, + native_types::{WitnessMap, WitnessStack}, + }, + pwg::ForeignCallWaitInfo, + AcirField, BlackBoxFunctionSolver, FieldElement, +}; +use noirc_abi::Abi; +use noirc_driver::{compile_no_check, CompileError, CompileOptions, DEFAULT_EXPRESSION_WIDTH}; +use noirc_errors::{debug_info::DebugInfo, FileDiagnostic}; +use noirc_frontend::hir::{def_map::TestFunction, Context}; + +use crate::{ + errors::try_to_diagnose_runtime_error, + foreign_calls::{layers, print::PrintOutput, ForeignCallError, ForeignCallExecutor}, + NargoError, +}; + +use super::execute_program; + +#[derive(Debug)] +pub enum TestStatus { + Pass, + Fail { message: String, error_diagnostic: Option }, + Skipped, + CompileError(FileDiagnostic), +} + +impl TestStatus { + pub fn failed(&self) -> bool { + !matches!(self, TestStatus::Pass | TestStatus::Skipped) + } +} + +pub fn run_test<'a, B, F, E>( + blackbox_solver: &B, + context: &mut Context, + test_function: &TestFunction, + output: PrintOutput<'a>, + config: &CompileOptions, + build_foreign_call_executor: F, +) -> TestStatus +where + B: BlackBoxFunctionSolver, + F: Fn(PrintOutput<'a>, layers::Unhandled) -> E + 'a, + E: ForeignCallExecutor, +{ + let test_function_has_no_arguments = context + .def_interner + .function_meta(&test_function.get_id()) + .function_signature() + .0 + .is_empty(); + + match compile_no_check(context, config, test_function.get_id(), None, false) { + Ok(compiled_program) => { + // Do the same optimizations as `compile_cmd`. + let target_width = config.expression_width.unwrap_or(DEFAULT_EXPRESSION_WIDTH); + let compiled_program = crate::ops::transform_program(compiled_program, target_width); + + if test_function_has_no_arguments { + // Run the backend to ensure the PWG evaluates functions like std::hash::pedersen, + // otherwise constraints involving these expressions will not error. + // Use a base layer that doesn't handle anything, which we handle in the `execute` below. + let inner_executor = build_foreign_call_executor(output, layers::Unhandled); + let mut foreign_call_executor = TestForeignCallExecutor::new(inner_executor); + + let circuit_execution = execute_program( + &compiled_program.program, + WitnessMap::new(), + blackbox_solver, + &mut foreign_call_executor, + ); + + let status = test_status_program_compile_pass( + test_function, + &compiled_program.abi, + &compiled_program.debug, + &circuit_execution, + ); + + let ignore_foreign_call_failures = + std::env::var("NARGO_IGNORE_TEST_FAILURES_FROM_FOREIGN_CALLS") + .is_ok_and(|var| &var == "true"); + + if let TestStatus::Fail { .. } = status { + if ignore_foreign_call_failures + && foreign_call_executor.encountered_unknown_foreign_call + { + TestStatus::Skipped + } else { + status + } + } else { + status + } + } else { + use acvm::acir::circuit::Program; + use noir_fuzzer::FuzzedExecutor; + use proptest::test_runner::Config; + use proptest::test_runner::TestRunner; + + let runner = + TestRunner::new(Config { failure_persistence: None, ..Config::default() }); + + let abi = compiled_program.abi.clone(); + let debug = compiled_program.debug.clone(); + + let executor = |program: &Program, + initial_witness: WitnessMap| + -> Result, String> { + // Use a base layer that doesn't handle anything, which we handle in the `execute` below. + let inner_executor = + build_foreign_call_executor(PrintOutput::None, layers::Unhandled); + + let mut foreign_call_executor = TestForeignCallExecutor::new(inner_executor); + + let circuit_execution = execute_program( + program, + initial_witness, + blackbox_solver, + &mut foreign_call_executor, + ); + + // Check if a failure was actually expected. + let status = test_status_program_compile_pass( + test_function, + &abi, + &debug, + &circuit_execution, + ); + + if let TestStatus::Fail { message, error_diagnostic: _ } = status { + Err(message) + } else { + // The fuzzer doesn't care about the actual result. + Ok(WitnessStack::default()) + } + }; + + let fuzzer = FuzzedExecutor::new(compiled_program.into(), executor, runner); + + let result = fuzzer.fuzz(); + if result.success { + TestStatus::Pass + } else { + TestStatus::Fail { + message: result.reason.unwrap_or_default(), + error_diagnostic: None, + } + } + } + } + Err(err) => test_status_program_compile_fail(err, test_function), + } +} + +/// Test function failed to compile +/// +/// Note: This could be because the compiler was able to deduce +/// 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 { + // The test has failed compilation, but it should never fail. Report error. + if !test_function.should_fail() { + return TestStatus::CompileError(err.into()); + } + + check_expected_failure_message(test_function, None, Some(err.into())) +} + +/// The test function compiled successfully. +/// +/// 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, + abi: &Abi, + debug: &[DebugInfo], + circuit_execution: &Result, NargoError>, +) -> TestStatus { + let circuit_execution_err = match circuit_execution { + // Circuit execution was successful; ie no errors or unsatisfied constraints + // were encountered. + Ok(_) => { + if test_function.should_fail() { + return TestStatus::Fail { + message: "error: Test passed when it should have failed".to_string(), + error_diagnostic: None, + }; + } + return TestStatus::Pass; + } + Err(err) => err, + }; + + // 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, abi, debug); + let test_should_have_passed = !test_function.should_fail(); + if test_should_have_passed { + return TestStatus::Fail { + message: circuit_execution_err.to_string(), + error_diagnostic: diagnostic, + }; + } + + check_expected_failure_message( + test_function, + circuit_execution_err.user_defined_failure_message(&abi.error_types), + diagnostic, + ) +} + +fn check_expected_failure_message( + test_function: &TestFunction, + failed_assertion: Option, + error_diagnostic: Option, +) -> TestStatus { + // Extract the expected failure message, if there was one + // + // #[test(should_fail)] will not produce any message + // #[test(should_fail_with = "reason")] will produce a message + // + let expected_failure_message = match test_function.failure_reason() { + Some(reason) => reason, + None => return TestStatus::Pass, + }; + + // Match the failure message that the user will see, i.e. the failed_assertion + // if present or else the error_diagnostic's message, against the + // expected_failure_message + let expected_failure_message_matches = failed_assertion + .as_ref() + .or_else(|| { + error_diagnostic.as_ref().map(|file_diagnostic| &file_diagnostic.diagnostic.message) + }) + .map(|message| message.contains(expected_failure_message)) + .unwrap_or(false); + if expected_failure_message_matches { + return TestStatus::Pass; + } + + // The expected failure message does not match the actual failure message + TestStatus::Fail { + message: format!( + "\nerror: Test failed with the wrong message. \nExpected: {} \nGot: {}", + test_function.failure_reason().unwrap_or_default(), + failed_assertion.unwrap_or_default().trim_matches('\'') + ), + error_diagnostic, + } +} + +/// A specialized foreign call executor which tracks whether it has encountered any unknown foreign calls +struct TestForeignCallExecutor { + executor: E, + encountered_unknown_foreign_call: bool, +} + +impl TestForeignCallExecutor { + fn new(executor: E) -> Self { + Self { executor, encountered_unknown_foreign_call: false } + } +} + +impl ForeignCallExecutor for TestForeignCallExecutor +where + F: AcirField, + E: ForeignCallExecutor, +{ + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + // If the circuit has reached a new foreign call opcode then it can't have failed from any previous unknown foreign calls. + self.encountered_unknown_foreign_call = false; + match self.executor.execute(foreign_call) { + Err(ForeignCallError::NoHandler(_)) => { + self.encountered_unknown_foreign_call = true; + // If the inner executor cannot handle this foreign call, then it's very likely that this is a custom + // foreign call. We then return an empty response in case the foreign call doesn't need return values. + layers::Empty.execute(foreign_call) + } + other => other, + } + } +} diff --git a/tooling/nargo/src/ops/transform.rs b/tooling/nargo/src/ops/transform.rs new file mode 100644 index 00000000000..fdda368d150 --- /dev/null +++ b/tooling/nargo/src/ops/transform.rs @@ -0,0 +1,56 @@ +use acvm::{ + acir::circuit::{ExpressionWidth, Program}, + FieldElement, +}; +use iter_extended::vecmap; +use noirc_driver::{CompiledContract, CompiledProgram}; +use noirc_errors::debug_info::DebugInfo; + +/// Apply ACVM optimizations on the circuit. +pub fn transform_program( + mut compiled_program: CompiledProgram, + expression_width: ExpressionWidth, +) -> CompiledProgram { + compiled_program.program = transform_program_internal( + compiled_program.program, + &mut compiled_program.debug, + expression_width, + ); + compiled_program +} + +/// Apply the optimizing transformation on each function in the contract. +pub fn transform_contract( + contract: CompiledContract, + expression_width: ExpressionWidth, +) -> CompiledContract { + let functions = vecmap(contract.functions, |mut func| { + 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 new file mode 100644 index 00000000000..cd1d5e2a84f --- /dev/null +++ b/tooling/nargo/src/package.rs @@ -0,0 +1,76 @@ +use std::{collections::BTreeMap, fmt::Display, path::PathBuf}; + +use acvm::acir::circuit::ExpressionWidth; +pub use noirc_driver::CrateName; + +use crate::constants::PROVER_INPUT_FILE; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum PackageType { + Library, + Binary, + Contract, +} + +impl Display for PackageType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Library => write!(f, "lib"), + Self::Binary => write!(f, "bin"), + Self::Contract => write!(f, "contract"), + } + } +} + +#[derive(Clone)] +pub enum Dependency { + Local { package: Package }, + Remote { package: Package }, +} + +impl Dependency { + pub fn is_binary(&self) -> bool { + match self { + Self::Local { package } | Self::Remote { package } => package.is_binary(), + } + } + + pub fn package_name(&self) -> &CrateName { + match self { + Self::Local { package } | Self::Remote { package } => &package.name, + } + } +} + +#[derive(Clone)] +pub struct Package { + pub version: Option, + // A semver string which specifies the compiler version required to compile this package + pub compiler_required_version: Option, + pub root_dir: PathBuf, + pub package_type: PackageType, + pub entry_path: PathBuf, + pub name: CrateName, + pub dependencies: BTreeMap, + pub expression_width: Option, +} + +impl Package { + pub fn prover_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!("{PROVER_INPUT_FILE}.toml")) + } + + pub fn is_binary(&self) -> bool { + self.package_type == PackageType::Binary + } + + pub fn is_contract(&self) -> bool { + self.package_type == PackageType::Contract + } + + pub fn is_library(&self) -> bool { + self.package_type == PackageType::Library + } +} diff --git a/tooling/nargo/src/workspace.rs b/tooling/nargo/src/workspace.rs new file mode 100644 index 00000000000..810a9edb7e1 --- /dev/null +++ b/tooling/nargo/src/workspace.rs @@ -0,0 +1,102 @@ +// We will say that a cargo unit must contain either a binary or a library +// Then we use workspace to allow more than one. In the future, do not allow there to be +// both a binary and a library. +// - library will be default + +use std::{ + iter::{once, Once}, + path::PathBuf, + slice, +}; + +use fm::FileManager; +use noirc_driver::file_manager_with_stdlib; + +use crate::{ + constants::{CONTRACT_DIR, EXPORT_DIR, PROOFS_DIR, TARGET_DIR}, + package::Package, +}; + +#[derive(Clone)] +pub struct Workspace { + pub root_dir: PathBuf, + pub members: Vec, + // If `Some()`, the `selected_package_index` is used to select the only `Package` when iterating a Workspace + pub selected_package_index: Option, + /// If we could not resolve the workspace we would inform the user we have assumed it (ie. from lsp file path given) + pub is_assumed: bool, +} + +impl Workspace { + pub fn package_build_path(&self, package: &Package) -> PathBuf { + let name: String = package.name.clone().into(); + self.target_directory_path().join(name).with_extension("json") + } + + pub fn contracts_directory_path(&self, package: &Package) -> PathBuf { + let name: String = package.name.clone().into(); + self.root_dir.join(CONTRACT_DIR).join(name) + } + + pub fn proofs_directory_path(&self) -> PathBuf { + self.root_dir.join(PROOFS_DIR) + } + + pub fn target_directory_path(&self) -> PathBuf { + self.root_dir.join(TARGET_DIR) + } + + pub fn export_directory_path(&self) -> PathBuf { + self.root_dir.join(EXPORT_DIR) + } + + /// Returns a new `FileManager` for the root directory of this workspace. + /// If the root directory is not the standard library, the standard library + /// is added to the returned `FileManager`. + pub fn new_file_manager(&self) -> FileManager { + if self.is_stdlib() { + FileManager::new(&self.root_dir) + } else { + file_manager_with_stdlib(&self.root_dir) + } + } + + fn is_stdlib(&self) -> bool { + self.members.len() == 1 && self.members[0].name.to_string() == "std" + } +} + +pub enum IntoIter<'a, T> { + Only(Once<&'a T>), + All(slice::Iter<'a, T>), +} + +impl<'a> IntoIterator for &'a Workspace { + type Item = &'a Package; + type IntoIter = IntoIter<'a, Package>; + + fn into_iter(self) -> Self::IntoIter { + if let Some(index) = self.selected_package_index { + // Precondition: The selected_package_index was verified to be in-bounds before constructing workspace + let member = self + .members + .get(index) + .expect("Workspace constructed with invalid selected_package_index"); + + IntoIter::Only(once(member)) + } else { + IntoIter::All(self.members.iter()) + } + } +} + +impl<'a> Iterator for IntoIter<'a, Package> { + type Item = &'a Package; + + fn next(&mut self) -> Option { + match self { + Self::Only(iter) => iter.next(), + Self::All(iter) => iter.next(), + } + } +} diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml new file mode 100644 index 00000000000..001306bb162 --- /dev/null +++ b/tooling/nargo_cli/Cargo.toml @@ -0,0 +1,116 @@ +[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 + +[lints] +workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +# Rename binary from `nargo_cli` to `nargo` +[[bin]] +name = "nargo" +path = "src/main.rs" + +[build-dependencies] +build-data.workspace = true +toml.workspace = true + +[dependencies] +clap.workspace = true +fm.workspace = true +fxhash.workspace = true +iter-extended.workspace = true +# This is the only crate that really needs the RPC feature, +# but enabling it here implicitly enables it for the whole +# workspace. A crate could opt out using `path` dependency, +# but it's only `noir_wasm` which couldn't compile with it, +# and that is a different target, and for that the feature +# aren't unified with this one. +nargo = { workspace = true, features = ["rpc"] } +nargo_fmt.workspace = true +nargo_toml.workspace = true +noir_lsp.workspace = true +noir_debugger.workspace = true +noirc_driver = { workspace = true, features = ["bn254"] } +noirc_frontend = { workspace = true, features = ["bn254"] } +noirc_abi.workspace = true +noirc_errors.workspace = true +noirc_artifacts.workspace = true +acvm = { workspace = true, features = ["bn254"] } +bn254_blackbox_solver.workspace = true +toml.workspace = true +serde.workspace = true +serde_json.workspace = true +prettytable-rs = "0.10" +rayon.workspace = true +thiserror.workspace = true +tower.workspace = true +async-lsp = { workspace = true, features = [ + "client-monitor", + "stdio", + "tracing", + "tokio", +] } +const_format.workspace = true +similar-asserts.workspace = true +termcolor = "1.1.2" +color-eyre.workspace = true +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 } + +notify = "6.1.1" +notify-debouncer-full = "0.3.1" +termion = "3.0.0" + +# Logs +tracing.workspace = true +tracing-subscriber.workspace = true +tracing-appender = "0.2.3" +clap_complete = "4.5.36" +fs2 = "0.4.3" + +[target.'cfg(not(unix))'.dependencies] +tokio-util = { version = "0.7.8", features = ["compat"] } + +[dev-dependencies] +ark-bn254.workspace = true +tempfile.workspace = true +dirs.workspace = true +assert_cmd = "2.0.8" +assert_fs = "1.0.10" +predicates = "2.1.5" +fm.workspace = true +criterion.workspace = true +pprof.workspace = true +paste = "1.0.14" +proptest.workspace = true +sha2.workspace = true +sha3.workspace = true +iai = "0.1.1" +test-case.workspace = true +lazy_static.workspace = true +light-poseidon = "0.2.0" + +ark-bn254-v04 = { package = "ark-bn254", version = "^0.4.0", default-features = false, features = [ + "curve", +] } +ark-ff-v04 = { package = "ark-ff", version = "^0.4.0", default-features = false } + +[[bench]] +name = "criterion" +harness = false + +[[bench]] +name = "iai" +harness = false + +[features] +codegen-docs = ["dep:clap-markdown"] diff --git a/tooling/nargo_cli/benches/README.md b/tooling/nargo_cli/benches/README.md new file mode 100644 index 00000000000..a579b82bbb5 --- /dev/null +++ b/tooling/nargo_cli/benches/README.md @@ -0,0 +1,13 @@ +# Benchmarks + +To generate flamegraphs for the execution of a specific program, execute the following commands: + +```shell +./scripts/benchmark_start.sh +cargo bench -p nargo_cli --bench criterion -- --profile-time=30 +./scripts/benchmark_stop.sh +``` + +Afterwards the flamegraph is available at `target/criterion/_execute/profile/flamegraph.svg` + +Alternatively, omit `` to run profiling on all test programs defined in [utils.rs](./utils.rs). \ No newline at end of file diff --git a/tooling/nargo_cli/benches/criterion.rs b/tooling/nargo_cli/benches/criterion.rs new file mode 100644 index 00000000000..e43e498ea06 --- /dev/null +++ b/tooling/nargo_cli/benches/criterion.rs @@ -0,0 +1,173 @@ +//! Select representative tests to bench with criterion +use acvm::{acir::native_types::WitnessMap, FieldElement}; +use assert_cmd::prelude::{CommandCargoExt, OutputAssertExt}; +use criterion::{criterion_group, criterion_main, Criterion}; + +use noirc_abi::{ + input_parser::{Format, InputValue}, + Abi, InputMap, +}; +use noirc_artifacts::program::ProgramArtifact; +use noirc_driver::CompiledProgram; +use pprof::criterion::{Output, PProfProfiler}; +use std::hint::black_box; +use std::path::Path; +use std::{cell::RefCell, collections::BTreeMap}; +use std::{process::Command, time::Duration}; + +include!("./utils.rs"); + +/// Compile the test program in a sub-process +/// The `force_brillig` option is used to benchmark the program as if it was executed by the AVM. +fn compile_program(test_program_dir: &Path, force_brillig: bool) { + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(test_program_dir); + cmd.arg("compile"); + cmd.arg("--force"); + if force_brillig { + cmd.arg("--force-brillig"); + } + cmd.assert().success(); +} + +/// Read the bytecode(s) of the program(s) from the compilation artifacts +/// from all the binary packages. Pair them up with their respective input. +/// +/// Based on `ExecuteCommand::run`. +fn read_compiled_programs_and_inputs( + dir: &Path, +) -> Vec<(CompiledProgram, WitnessMap)> { + let toml_path = nargo_toml::get_package_manifest(dir).expect("failed to read manifest"); + let workspace = nargo_toml::resolve_workspace_from_toml( + &toml_path, + nargo_toml::PackageSelection::All, + Some(noirc_driver::NOIR_ARTIFACT_VERSION_STRING.to_string()), + ) + .expect("failed to resolve workspace"); + + let mut programs = Vec::new(); + let binary_packages = workspace.into_iter().filter(|package| package.is_binary()); + + for package in binary_packages { + let program_artifact_path = workspace.package_build_path(package); + let program: CompiledProgram = read_program_from_file(&program_artifact_path).into(); + + let (inputs, _) = read_inputs_from_file( + &package.root_dir, + nargo::constants::PROVER_INPUT_FILE, + Format::Toml, + &program.abi, + ); + + let initial_witness = + program.abi.encode(&inputs, None).expect("failed to encode input witness"); + + programs.push((program, initial_witness)); + } + programs +} + +/// Read the bytecode and ABI from the compilation output +fn read_program_from_file(circuit_path: &Path) -> ProgramArtifact { + let file_path = circuit_path.with_extension("json"); + let input_string = std::fs::read(file_path).expect("failed to read artifact file"); + serde_json::from_slice(&input_string).expect("failed to deserialize artifact") +} + +/// Read the inputs from Prover.toml +fn read_inputs_from_file( + path: &Path, + file_name: &str, + format: Format, + abi: &Abi, +) -> (InputMap, Option) { + if abi.is_empty() { + return (BTreeMap::new(), None); + } + + let file_path = path.join(file_name).with_extension(format.ext()); + if !file_path.exists() { + if abi.parameters.is_empty() { + return (BTreeMap::new(), None); + } else { + panic!("input file doesn't exist: {}", file_path.display()); + } + } + + let input_string = std::fs::read_to_string(file_path).expect("failed to read input file"); + let mut input_map = format.parse(&input_string, abi).expect("failed to parse input"); + let return_value = input_map.remove(noirc_abi::MAIN_RETURN_NAME); + + (input_map, return_value) +} + +/// Use the nargo CLI to compile a test program, then benchmark its execution +/// by executing the command directly from the benchmark, so that we can have +/// meaningful flamegraphs about the ACVM. +fn criterion_test_execution(c: &mut Criterion, test_program_dir: &Path, force_brillig: bool) { + let benchmark_name = format!( + "{}_execute{}", + test_program_dir.file_name().unwrap().to_str().unwrap(), + if force_brillig { "_brillig" } else { "" } + ); + + // The program and its inputs will be populated in the first setup. + let artifacts = RefCell::new(None); + + let mut foreign_call_executor = + nargo::foreign_calls::DefaultForeignCallBuilder::default().build(); + + c.bench_function(&benchmark_name, |b| { + b.iter_batched( + || { + // Setup will be called many times to set a batch (which we don't use), + // but we can compile it only once, and then the executions will not have to do so. + // It is done as a setup so that we only compile the test programs that we filter for. + if artifacts.borrow().is_some() { + return; + } + compile_program(test_program_dir, force_brillig); + // Parse the artifacts for use in the benchmark routine + let programs = read_compiled_programs_and_inputs(test_program_dir); + // Warn, but don't stop, if we haven't found any binary packages. + if programs.is_empty() { + eprintln!("\nWARNING: There is nothing to benchmark in {benchmark_name}"); + } + // Store them for execution + artifacts.replace(Some(programs)); + }, + |_| { + let artifacts = artifacts.borrow(); + let artifacts = artifacts.as_ref().expect("setup compiled them"); + + for (program, initial_witness) in artifacts { + let solver = bn254_blackbox_solver::Bn254BlackBoxSolver::default(); + let _witness_stack = black_box(nargo::ops::execute_program( + black_box(&program.program), + black_box(initial_witness.clone()), + &solver, + &mut foreign_call_executor, + )) + .expect("failed to execute program"); + } + }, + criterion::BatchSize::SmallInput, + ); + }); +} + +/// Go through all the selected tests and executem with and without Brillig. +fn criterion_selected_tests_execution(c: &mut Criterion) { + for test_program_dir in get_selected_tests() { + for force_brillig in [false, true] { + criterion_test_execution(c, &test_program_dir, force_brillig); + } + } +} + +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_main!(execution_benches); diff --git a/tooling/nargo_cli/benches/iai.rs b/tooling/nargo_cli/benches/iai.rs new file mode 100644 index 00000000000..bcd60111ccf --- /dev/null +++ b/tooling/nargo_cli/benches/iai.rs @@ -0,0 +1,25 @@ +//! Select representative tests to bench with iai +use assert_cmd::prelude::{CommandCargoExt, OutputAssertExt}; +use iai::black_box; +use paste::paste; +use std::process::Command; +include!("./utils.rs"); + +macro_rules! iai_command { + ($command_name:tt, $command_string:expr) => { + paste! { + fn []() { + let test_program_dirs = get_selected_tests(); + for test_program_dir in test_program_dirs { + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("--program-dir").arg(&test_program_dir); + cmd.arg($command_string); + + black_box(cmd.assert()); + } + } + } + }; +} +iai_command!(execution, "execute"); +iai::main!(iai_selected_tests_execution); diff --git a/tooling/nargo_cli/benches/utils.rs b/tooling/nargo_cli/benches/utils.rs new file mode 100644 index 00000000000..37c94241b08 --- /dev/null +++ b/tooling/nargo_cli/benches/utils.rs @@ -0,0 +1,26 @@ +use std::path::PathBuf; + +#[allow(unused)] +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(), + }; + + let test_dir = manifest_dir + .parent() + .unwrap() + .parent() + .unwrap() + .join("test_programs") + .join("execution_success"); + + let selected_tests = vec!["struct", "eddsa", "regression"]; + let mut selected_tests = + selected_tests.into_iter().map(|t| test_dir.join(t)).collect::>(); + + let test_dir = test_dir.parent().unwrap().join("benchmarks"); + selected_tests.extend(test_dir.read_dir().unwrap().filter_map(|e| e.ok()).map(|e| e.path())); + + selected_tests +} diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs new file mode 100644 index 00000000000..3b1aff88755 --- /dev/null +++ b/tooling/nargo_cli/build.rs @@ -0,0 +1,494 @@ +use std::fs::File; +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::{env, fs}; + +const GIT_COMMIT: &&str = &"GIT_COMMIT"; + +fn main() { + // Only use build_data if the environment variable isn't set. + if env::var(GIT_COMMIT).is_err() { + build_data::set_GIT_COMMIT(); + build_data::set_GIT_DIRTY(); + build_data::no_debug_rebuilds(); + } + + let out_dir = env::var("OUT_DIR").unwrap(); + let destination = Path::new(&out_dir).join("execute.rs"); + let mut test_file = File::create(destination).unwrap(); + + // Try to find the directory that Cargo sets when it is running; otherwise fallback to assuming the CWD + // is the root of the repository and append the crate path + let root_dir = match env::var("CARGO_MANIFEST_DIR") { + Ok(dir) => PathBuf::from(dir).parent().unwrap().parent().unwrap().to_path_buf(), + Err(_) => env::current_dir().unwrap(), + }; + let test_dir = root_dir.join("test_programs"); + + // Rebuild if the tests have changed + println!("cargo:rerun-if-changed=tests"); + 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); + generate_compile_success_contract_tests(&mut test_file, &test_dir); + generate_compile_success_no_bug_tests(&mut test_file, &test_dir); + generate_compile_success_with_bug_tests(&mut test_file, &test_dir); + 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; 10] = [ + // 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", +]; + +/// Tests which aren't expected to work with the default inliner cases. +const INLINER_MIN_OVERRIDES: [(&str, i64); 1] = [ + // 0 works if PoseidonHasher::write is tagged as `inline_always`, otherwise 22. + ("eddsa", 0), +]; + +/// Some tests are expected to have warnings +/// These should be fixed and removed from this list. +const TESTS_WITH_EXPECTED_WARNINGS: [&str; 2] = [ + // TODO(https://github.com/noir-lang/noir/issues/6238): remove from list once issue is closed + "brillig_cast", + // TODO(https://github.com/noir-lang/noir/issues/6238): remove from list once issue is closed + "macros_in_comptime", +]; + +fn read_test_cases( + test_data_dir: &Path, + test_sub_dir: &str, +) -> impl Iterator { + 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()); + + test_case_dirs.into_iter().filter_map(|dir| { + // When switching git branches we might end up with non-empty directories that have a `target` + // directory inside them but no `Nargo.toml`. + // These "tests" would always fail, but it's okay to ignore them so we do that here. + if !dir.path().join("Nargo.toml").exists() { + return None; + } + + let test_name = + 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 `_`" + ); + } + Some((test_name, dir.path())) + }) +} + +#[derive(Default)] +struct MatrixConfig { + // Only used with execution, and only on selected tests. + vary_brillig: bool, + // Only seems to have an effect on the `execute_success` cases. + vary_inliner: bool, + // If there is a non-default minimum inliner aggressiveness to use with the brillig tests. + min_inliner: i64, +} + +// Enum to be able to preserve readable test labels and also compare to numbers. +enum Inliner { + Min, + Default, + Max, + Custom(i64), +} + +impl Inliner { + fn value(&self) -> i64 { + match self { + Inliner::Min => i64::MIN, + Inliner::Default => 0, + Inliner::Max => i64::MAX, + Inliner::Custom(i) => *i, + } + } + fn label(&self) -> String { + match self { + Inliner::Min => "i64::MIN".to_string(), + Inliner::Default => "0".to_string(), + Inliner::Max => "i64::MAX".to_string(), + Inliner::Custom(i) => i.to_string(), + } + } +} + +/// Generate all test cases for a given test name (expected to be unique for the test directory), +/// based on the matrix configuration. These will be executed serially, but concurrently with +/// other test directories. Running multiple tests on the same directory would risk overriding +/// each others compilation artifacts, which is why this method injects a mutex shared by +/// all cases in the test matrix, as long as the test name and directory has a 1-to-1 relationship. +fn generate_test_cases( + test_file: &mut File, + test_name: &str, + test_dir: &std::path::Display, + test_command: &str, + test_content: &str, + matrix_config: &MatrixConfig, +) { + let brillig_cases = if matrix_config.vary_brillig { vec![false, true] } else { vec![false] }; + let inliner_cases = if matrix_config.vary_inliner { + let mut cases = vec![Inliner::Min, Inliner::Default, Inliner::Max]; + if !cases.iter().any(|c| c.value() == matrix_config.min_inliner) { + cases.push(Inliner::Custom(matrix_config.min_inliner)); + } + cases + } else { + vec![Inliner::Default] + }; + + // We can't use a `#[test_matrix(brillig_cases, inliner_cases)` if we only want to limit the + // aggressiveness range for the brillig tests, and let them go full range on the ACIR case. + let mut test_cases = Vec::new(); + for brillig in &brillig_cases { + for inliner in &inliner_cases { + if *brillig && inliner.value() < matrix_config.min_inliner { + continue; + } + test_cases.push(format!( + "#[test_case::test_case(ForceBrillig({brillig}), Inliner({}))]", + inliner.label() + )); + } + } + let test_cases = test_cases.join("\n"); + + write!( + test_file, + r#" +{test_cases} +fn test_{test_name}(force_brillig: ForceBrillig, inliner_aggressiveness: Inliner) {{ + let test_program_dir = PathBuf::from("{test_dir}"); + + let mut nargo = Command::cargo_bin("nargo").unwrap(); + nargo.arg("--program-dir").arg(test_program_dir); + nargo.arg("{test_command}").arg("--force"); + nargo.arg("--inliner-aggressiveness").arg(inliner_aggressiveness.0.to_string()); + // Check whether the test case is non-deterministic + nargo.arg("--check-non-determinism"); + + if force_brillig.0 {{ + nargo.arg("--force-brillig"); + + // Set the maximum increase so that part of the optimization is exercised (it might fail). + nargo.arg("--max-bytecode-increase-percent"); + nargo.arg("50"); + }} + + {test_content} +}} +"# + ) + .expect("Could not write templated test file."); +} + +fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "execution_success"; + let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + + generate_test_cases( + test_file, + &test_name, + &test_dir, + "execute", + r#" + nargo.assert().success(); + "#, + &MatrixConfig { + vary_brillig: !IGNORED_BRILLIG_TESTS.contains(&test_name.as_str()), + vary_inliner: true, + min_inliner: INLINER_MIN_OVERRIDES + .iter() + .find(|(n, _)| *n == test_name.as_str()) + .map(|(_, i)| *i) + .unwrap_or(i64::MIN), + }, + ); + } + writeln!(test_file, "}}").unwrap(); +} + +fn generate_execution_failure_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "execution_failure"; + let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + + generate_test_cases( + test_file, + &test_name, + &test_dir, + "execute", + r#" + nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); + "#, + &MatrixConfig::default(), + ); + } + writeln!(test_file, "}}").unwrap(); +} + +fn generate_noir_test_success_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "noir_test_success"; + let test_cases = read_test_cases(test_data_dir, "noir_test_success"); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + + generate_test_cases( + test_file, + &test_name, + &test_dir, + "test", + r#" + nargo.assert().success(); + "#, + &MatrixConfig::default(), + ); + } + writeln!(test_file, "}}").unwrap(); +} + +fn generate_noir_test_failure_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "noir_test_failure"; + let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + generate_test_cases( + test_file, + &test_name, + &test_dir, + "test", + r#" + nargo.assert().failure(); + "#, + &MatrixConfig::default(), + ); + } + writeln!(test_file, "}}").unwrap(); +} + +fn generate_compile_success_empty_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "compile_success_empty"; + let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + + let mut assert_zero_opcodes = r#" + let output = nargo.output().expect("Failed to execute command"); + + if !output.status.success() {{ + panic!("`nargo info` failed with: {}", String::from_utf8(output.stderr).unwrap_or_default()); + }} + "#.to_string(); + + if !TESTS_WITH_EXPECTED_WARNINGS.contains(&test_name.as_str()) { + assert_zero_opcodes += r#" + nargo.assert().success().stderr(predicate::str::contains("warning:").not()); + "#; + } + + assert_zero_opcodes += r#" + // `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]["functions"][0]["opcodes"]; + assert_eq!(num_opcodes.as_u64().expect("number of opcodes should fit in a u64"), 0, "expected the number of opcodes to be 0"); + "#; + + generate_test_cases( + test_file, + &test_name, + &test_dir, + "info", + &format!( + r#" + nargo.arg("--json"); + {assert_zero_opcodes} + "#, + ), + &MatrixConfig::default(), + ); + } + writeln!(test_file, "}}").unwrap(); +} + +fn generate_compile_success_contract_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "compile_success_contract"; + let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + + generate_test_cases( + test_file, + &test_name, + &test_dir, + "compile", + r#" + nargo.assert().success().stderr(predicate::str::contains("warning:").not()); + "#, + &MatrixConfig::default(), + ); + } + writeln!(test_file, "}}").unwrap(); +} + +/// Generate tests for checking that the contract compiles and there are no "bugs" in stderr +fn generate_compile_success_no_bug_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "compile_success_no_bug"; + let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + + generate_test_cases( + test_file, + &test_name, + &test_dir, + "compile", + r#" + nargo.assert().success().stderr(predicate::str::contains("bug:").not()); + "#, + &MatrixConfig::default(), + ); + } + writeln!(test_file, "}}").unwrap(); +} + +/// Generate tests for checking that the contract compiles and there are "bugs" in stderr +fn generate_compile_success_with_bug_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "compile_success_with_bug"; + let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + + generate_test_cases( + test_file, + &test_name, + &test_dir, + "compile", + r#" + nargo.assert().success().stderr(predicate::str::contains("bug:")); + "#, + &MatrixConfig::default(), + ); + } + writeln!(test_file, "}}").unwrap(); +} + +fn generate_compile_failure_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "compile_failure"; + let test_cases = read_test_cases(test_data_dir, test_type); + + writeln!( + test_file, + "mod {test_type} {{ + use super::*; + " + ) + .unwrap(); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + + generate_test_cases( + test_file, + &test_name, + &test_dir, + "compile", + r#" + nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); + "#, + &MatrixConfig::default(), + ); + } + writeln!(test_file, "}}").unwrap(); +} diff --git a/tooling/nargo_cli/src/cli/check_cmd.rs b/tooling/nargo_cli/src/cli/check_cmd.rs new file mode 100644 index 00000000000..c8695a8f626 --- /dev/null +++ b/tooling/nargo_cli/src/cli/check_cmd.rs @@ -0,0 +1,194 @@ +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, ops::report_errors, + package::Package, parse_all, prepare_package, +}; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; +use noirc_abi::{AbiParameter, AbiType, MAIN_RETURN_NAME}; +use noirc_driver::{ + check_crate, compute_function_abi, CompileOptions, CrateId, NOIR_ARTIFACT_VERSION_STRING, +}; +use noirc_frontend::hir::{Context, ParsedFiles}; + +use super::NargoConfig; +use super::{fs::write_to_file, PackageOptions}; + +/// Checks the constraint system for errors +#[derive(Debug, Clone, Args)] +#[clap(visible_alias = "c")] +pub(crate) struct CheckCommand { + #[clap(flatten)] + pub(super) package_options: PackageOptions, + + /// Force overwrite of existing files + #[clap(long = "overwrite")] + allow_overwrite: bool, + + #[clap(flatten)] + compile_options: CompileOptions, +} + +pub(crate) fn run(args: CheckCommand, config: NargoConfig) -> Result<(), CliError> { + let toml_path = get_package_manifest(&config.program_dir)?; + let selection = args.package_options.package_selection(); + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; + + let mut workspace_file_manager = workspace.new_file_manager(); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let parsed_files = parse_all(&workspace_file_manager); + + for package in &workspace { + 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, + allow_overwrite: bool, +) -> Result { + let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package); + check_crate_and_report_errors(&mut context, crate_id, compile_options)?; + + 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(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, _)) = compute_function_abi(&context, &crate_id) { + let path_to_prover_input = package.prover_input_path(); + + // 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."); + } + + let any_file_written = should_write_prover; + + Ok(any_file_written) + } else { + Err(CompileError::MissingMainFunction(package.name.clone())) + } + } +} + +/// Generates the contents of a toml file with fields for each of the passed parameters. +fn create_input_toml_template( + parameters: Vec, + return_type: Option, +) -> String { + /// Returns a default placeholder `toml::Value` for `typ` which + /// complies with the structure of the specified `AbiType`. + fn default_value(typ: AbiType) -> toml::Value { + match typ { + AbiType::Array { length, typ } => { + let default_value_vec = std::iter::repeat(default_value(*typ)) + .take(length.try_into().unwrap()) + .collect(); + toml::Value::Array(default_value_vec) + } + AbiType::Struct { fields, .. } => { + let default_value_map = toml::map::Map::from_iter( + fields.into_iter().map(|(name, typ)| (name, default_value(typ))), + ); + toml::Value::Table(default_value_map) + } + _ => toml::Value::String("".to_owned()), + } + } + + let mut map = + btree_map(parameters, |AbiParameter { name, typ, .. }| (name, default_value(typ))); + + if let Some(typ) = return_type { + map.insert(MAIN_RETURN_NAME.to_owned(), default_value(typ)); + } + + toml::to_string(&map).unwrap() +} + +/// Run the lexing, parsing, name resolution, and type checking passes and report any warnings +/// and errors found. +pub(crate) fn check_crate_and_report_errors( + context: &mut Context, + crate_id: CrateId, + options: &CompileOptions, +) -> Result<(), CompileError> { + let result = check_crate(context, crate_id, options); + report_errors(result, &context.file_manager, options.deny_warnings, options.silence_warnings) +} + +#[cfg(test)] +mod tests { + use noirc_abi::{AbiParameter, AbiType, AbiVisibility, Sign}; + + use super::create_input_toml_template; + + #[test] + fn valid_toml_template() { + let typed_param = |name: &str, typ: AbiType| AbiParameter { + name: name.to_string(), + typ, + visibility: AbiVisibility::Public, + }; + let parameters = vec![ + typed_param("a", AbiType::Field), + typed_param("b", AbiType::Integer { sign: Sign::Unsigned, width: 32 }), + typed_param("c", AbiType::Array { length: 2, typ: Box::new(AbiType::Field) }), + typed_param( + "d", + AbiType::Struct { + path: String::from("MyStruct"), + fields: vec![ + (String::from("d1"), AbiType::Field), + ( + String::from("d2"), + AbiType::Array { length: 3, typ: Box::new(AbiType::Field) }, + ), + ], + }, + ), + typed_param("e", AbiType::Boolean), + ]; + + let toml_str = create_input_toml_template(parameters, None); + + let expected_toml_str = r#"a = "" +b = "" +c = ["", ""] +e = "" + +[d] +d1 = "" +d2 = ["", "", ""] +"#; + assert_eq!(toml_str, expected_toml_str); + } +} diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs new file mode 100644 index 00000000000..0af05703c9a --- /dev/null +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -0,0 +1,457 @@ +use std::io::Write; +use std::path::Path; +use std::time::Duration; + +use acvm::acir::circuit::ExpressionWidth; +use fm::FileManager; +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}; +use nargo_toml::{ + get_package_manifest, resolve_workspace_from_toml, ManifestError, PackageSelection, +}; +use noirc_driver::DEFAULT_EXPRESSION_WIDTH; +use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; +use noirc_driver::{CompilationResult, CompileOptions, CompiledContract}; + +use clap::Args; +use noirc_frontend::hir::ParsedFiles; +use notify::{EventKind, RecursiveMode, Watcher}; +use notify_debouncer_full::new_debouncer; + +use crate::errors::CliError; + +use super::fs::program::{read_program_from_file, save_contract_to_file, save_program_to_file}; +use super::{NargoConfig, PackageOptions}; +use rayon::prelude::*; + +/// Compile the program and its secret execution trace into ACIR format +#[derive(Debug, Clone, Args)] +pub(crate) struct CompileCommand { + #[clap(flatten)] + pub(super) package_options: PackageOptions, + + #[clap(flatten)] + compile_options: CompileOptions, + + /// Watch workspace and recompile on changes. + #[clap(long, hide = true)] + watch: bool, +} + +pub(crate) fn run(args: CompileCommand, config: NargoConfig) -> Result<(), CliError> { + let selection = args.package_options.package_selection(); + let workspace = read_workspace(&config.program_dir, selection)?; + + 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(()) +} + +/// Read a given program directory into a workspace. +fn read_workspace( + program_dir: &Path, + selection: PackageSelection, +) -> Result { + let toml_path = get_package_manifest(program_dir)?; + + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_owned()), + )?; + + Ok(workspace) +} + +/// Continuously recompile the workspace on any Noir file change event. +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(()) +} + +/// Parse all files in the workspace. +fn parse_workspace(workspace: &Workspace) -> (FileManager, ParsedFiles) { + let mut file_manager = workspace.new_file_manager(); + insert_all_files_for_workspace_into_file_manager(workspace, &mut file_manager); + let parsed_files = parse_all(&file_manager); + (file_manager, parsed_files) +} + +/// Parse and compile the entire workspace, then report errors. +/// This is the main entry point used by all other commands that need compilation. +pub(super) fn compile_workspace_full( + workspace: &Workspace, + compile_options: &CompileOptions, +) -> Result<(), CliError> { + let (workspace_file_manager, parsed_files) = parse_workspace(workspace); + + let compiled_workspace = + compile_workspace(&workspace_file_manager, &parsed_files, workspace, compile_options); + + report_errors( + compiled_workspace, + &workspace_file_manager, + compile_options.deny_warnings, + compile_options.silence_warnings, + )?; + + Ok(()) +} + +/// Compile binary and contract packages. +/// Returns the merged warnings or errors. +fn compile_workspace( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + workspace: &Workspace, + compile_options: &CompileOptions, +) -> CompilationResult<()> { + let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace + .into_iter() + .filter(|package| !package.is_library()) + .cloned() + .partition(|package| package.is_binary()); + + // Compile all of the packages in parallel. + let program_warnings_or_errors: CompilationResult<()> = + compile_programs(file_manager, parsed_files, workspace, &binary_packages, compile_options); + + let contract_warnings_or_errors: CompilationResult<()> = compile_contracts( + file_manager, + parsed_files, + &contract_packages, + compile_options, + &workspace.target_directory_path(), + ); + + match (program_warnings_or_errors, contract_warnings_or_errors) { + (Ok((_, program_warnings)), Ok((_, contract_warnings))) => { + let warnings = [program_warnings, contract_warnings].concat(); + Ok(((), warnings)) + } + (Err(program_errors), Err(contract_errors)) => { + Err([program_errors, contract_errors].concat()) + } + (Err(errors), _) | (_, Err(errors)) => Err(errors), + } +} + +/// Compile the given binary packages in the workspace. +fn compile_programs( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + workspace: &Workspace, + binary_packages: &[Package], + compile_options: &CompileOptions, +) -> CompilationResult<()> { + // Load any existing artifact for a given package, _iff_ it was compiled with the same nargo version. + // The loaded circuit includes backend specific transformations, which might be different from the current target. + let load_cached_program = |package| { + let program_artifact_path = workspace.package_build_path(package); + read_program_from_file(program_artifact_path) + .ok() + .filter(|p| p.noir_version == NOIR_ARTIFACT_VERSION_STRING) + .map(|p| p.into()) + }; + + let compile_package = |package| { + let cached_program = load_cached_program(package); + + // Hash over the entire compiled program, including any post-compile transformations. + // This is used to detect whether `cached_program` is returned by `compile_program`. + let cached_hash = cached_program.as_ref().map(fxhash::hash64); + + // Compile the program, or use the cached artifacts if it matches. + let (program, warnings) = compile_program( + file_manager, + parsed_files, + workspace, + package, + compile_options, + cached_program, + )?; + + if compile_options.check_non_determinism { + let (program_two, _) = compile_program( + file_manager, + parsed_files, + workspace, + package, + compile_options, + load_cached_program(package), + )?; + if fxhash::hash64(&program) != fxhash::hash64(&program_two) { + panic!("Non deterministic result compiling {}", package.name); + } + } + + // Choose the target width for the final, backend specific transformation. + let target_width = + get_target_width(package.expression_width, compile_options.expression_width); + + // If the compiled program is the same as the cached one, we don't apply transformations again, unless the target width has changed. + // The transformations might not be idempotent, which would risk creating witnesses that don't work with earlier versions, + // based on which we might have generated a verifier already. + if cached_hash == Some(fxhash::hash64(&program)) { + let width_matches = program + .program + .functions + .iter() + .all(|circuit| circuit.expression_width == target_width); + + if width_matches { + return Ok(((), warnings)); + } + } + // Run ACVM optimizations and set the target width. + let program = nargo::ops::transform_program(program, target_width); + // Check solvability. + nargo::ops::check_program(&program)?; + // Overwrite the build artifacts with the final circuit, which includes the backend specific transformations. + save_program_to_file(&program.into(), &package.name, workspace.target_directory_path()); + + Ok(((), warnings)) + }; + + // Configure a thread pool with a larger stack size to prevent overflowing stack in large programs. + // Default is 2MB. + let pool = rayon::ThreadPoolBuilder::new().stack_size(4 * 1024 * 1024).build().unwrap(); + let program_results: Vec> = + pool.install(|| binary_packages.par_iter().map(compile_package).collect()); + + // Collate any warnings/errors which were encountered during compilation. + collect_errors(program_results).map(|(_, warnings)| ((), warnings)) +} + +/// Compile the given contracts in the workspace. +fn compile_contracts( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + contract_packages: &[Package], + compile_options: &CompileOptions, + target_dir: &Path, +) -> CompilationResult<()> { + let contract_results: Vec> = contract_packages + .par_iter() + .map(|package| { + let (contract, warnings) = + compile_contract(file_manager, parsed_files, package, compile_options)?; + let target_width = + get_target_width(package.expression_width, compile_options.expression_width); + let contract = nargo::ops::transform_contract(contract, target_width); + save_contract(contract, package, target_dir, compile_options.show_artifact_paths); + Ok(((), warnings)) + }) + .collect(); + + // Collate any warnings/errors which were encountered during compilation. + collect_errors(contract_results).map(|(_, warnings)| ((), warnings)) +} + +fn save_contract( + contract: CompiledContract, + package: &Package, + target_dir: &Path, + show_artifact_paths: bool, +) { + let contract_name = contract.name.clone(); + let artifact_path = save_contract_to_file( + &contract.into(), + &format!("{}-{}", package.name, contract_name), + target_dir, + ); + if show_artifact_paths { + println!("Saved contract artifact to: {}", artifact_path.display()); + } +} + +/// If a target width was not specified in the CLI we can safely override the default. +pub(crate) fn get_target_width( + package_default_width: Option, + compile_options_width: Option, +) -> ExpressionWidth { + if let (Some(manifest_default_width), None) = (package_default_width, compile_options_width) { + manifest_default_width + } else { + compile_options_width.unwrap_or(DEFAULT_EXPRESSION_WIDTH) + } +} + +#[cfg(test)] +mod tests { + use std::{ + path::{Path, PathBuf}, + str::FromStr, + }; + + use clap::Parser; + use nargo::ops::compile_program; + use nargo_toml::PackageSelection; + use noirc_driver::{CompileOptions, CrateName}; + + use crate::cli::compile_cmd::{get_target_width, parse_workspace, read_workspace}; + + /// Try to find the directory that Cargo sets when it is running; + /// otherwise fallback to assuming the CWD is the root of the repository + /// and append the crate path. + fn test_programs_dir() -> PathBuf { + let root_dir = match std::env::var("CARGO_MANIFEST_DIR") { + Ok(dir) => PathBuf::from(dir).parent().unwrap().parent().unwrap().to_path_buf(), + Err(_) => std::env::current_dir().unwrap(), + }; + root_dir.join("test_programs") + } + + /// Collect the test programs under a sub-directory. + fn read_test_program_dirs( + test_programs_dir: &Path, + test_sub_dir: &str, + ) -> impl Iterator { + let test_case_dir = test_programs_dir.join(test_sub_dir); + std::fs::read_dir(test_case_dir) + .unwrap() + .flatten() + .filter(|c| c.path().is_dir()) + .map(|c| c.path()) + } + + #[derive(Parser, Debug)] + #[command(ignore_errors = true)] + struct Options { + /// Test name to filter for. + /// + /// For example: + /// ```text + /// cargo test -p nargo_cli -- test_transform_program_is_idempotent slice_loop + /// ``` + args: Vec, + } + + impl Options { + fn package_selection(&self) -> PackageSelection { + match self.args.as_slice() { + [_test_name, test_program] => { + PackageSelection::Selected(CrateName::from_str(test_program).unwrap()) + } + _ => PackageSelection::DefaultOrAll, + } + } + } + + /// Check that `nargo::ops::transform_program` is idempotent by compiling the + /// test programs and running them through the optimizer twice. + /// + /// This test is here purely because of the convenience of having access to + /// the utility functions to process workspaces. + #[test] + fn test_transform_program_is_idempotent() { + let opts = Options::parse(); + + let sel = opts.package_selection(); + let verbose = matches!(sel, PackageSelection::Selected(_)); + + let test_workspaces = read_test_program_dirs(&test_programs_dir(), "execution_success") + .filter_map(|dir| read_workspace(&dir, sel.clone()).ok()) + .collect::>(); + + assert!(!test_workspaces.is_empty(), "should find some test workspaces"); + + test_workspaces.iter().for_each(|workspace| { + let (file_manager, parsed_files) = parse_workspace(workspace); + let binary_packages = workspace.into_iter().filter(|package| package.is_binary()); + + for package in binary_packages { + let (program_0, _warnings) = compile_program( + &file_manager, + &parsed_files, + workspace, + package, + &CompileOptions::default(), + None, + ) + .expect("failed to compile"); + + let width = get_target_width(package.expression_width, None); + + let program_1 = nargo::ops::transform_program(program_0, width); + let program_2 = nargo::ops::transform_program(program_1.clone(), width); + + if verbose { + // Compare where the most likely difference is. + similar_asserts::assert_eq!( + format!("{}", program_1.program), + format!("{}", program_2.program), + "optimization not idempotent for test program '{}'", + package.name + ); + assert_eq!( + program_1.program, program_2.program, + "optimization not idempotent for test program '{}'", + package.name + ); + + // Compare the whole content. + similar_asserts::assert_eq!( + serde_json::to_string_pretty(&program_1).unwrap(), + serde_json::to_string_pretty(&program_2).unwrap(), + "optimization not idempotent for test program '{}'", + package.name + ); + } else { + // Just compare hashes, which would just state that the program failed. + // Then we can use the filter option to zoom in one one to see why. + assert!( + fxhash::hash64(&program_1) == fxhash::hash64(&program_2), + "optimization not idempotent for test program '{}'", + package.name + ); + } + } + }); + } +} diff --git a/tooling/nargo_cli/src/cli/dap_cmd.rs b/tooling/nargo_cli/src/cli/dap_cmd.rs new file mode 100644 index 00000000000..7fbf685688a --- /dev/null +++ b/tooling/nargo_cli/src/cli/dap_cmd.rs @@ -0,0 +1,281 @@ +use acvm::acir::circuit::ExpressionWidth; +use acvm::acir::native_types::WitnessMap; +use acvm::FieldElement; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use clap::Args; +use nargo::constants::PROVER_INPUT_FILE; +use nargo::workspace::Workspace; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_abi::input_parser::Format; +use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_frontend::graph::CrateName; + +use std::io::{BufReader, BufWriter, Read, Write}; +use std::path::Path; + +use dap::requests::Command; +use dap::responses::ResponseBody; +use dap::server::Server; +use dap::types::Capabilities; +use serde_json::Value; + +use super::debug_cmd::compile_bin_package_for_debugging; +use super::fs::inputs::read_inputs_from_file; +use crate::errors::CliError; + +use super::NargoConfig; + +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, default_value = "4")] + expression_width: ExpressionWidth, + + #[clap(long)] + preflight_check: bool, + + #[clap(long)] + preflight_project_folder: Option, + + #[clap(long)] + preflight_package: Option, + + #[clap(long)] + preflight_prover_name: Option, + + #[clap(long)] + preflight_generate_acir: bool, + + #[clap(long)] + preflight_skip_instrumentation: bool, + + /// Use pedantic ACVM solving, i.e. double-check some black-box function + /// assumptions when solving. + /// This is disabled by default. + #[arg(long, default_value = "false")] + pedantic_solving: bool, +} + +fn parse_expression_width(input: &str) -> Result { + use std::io::{Error, ErrorKind}; + + let width = input + .parse::() + .map_err(|err| Error::new(ErrorKind::InvalidInput, err.to_string()))?; + + match width { + 0 => Ok(ExpressionWidth::Unbounded), + _ => Ok(ExpressionWidth::Bounded { width }), + } +} + +fn find_workspace(project_folder: &str, package: Option<&str>) -> Option { + let Ok(toml_path) = get_package_manifest(Path::new(project_folder)) else { + eprintln!("ERROR: Failed to get package manifest"); + return None; + }; + let package = package.and_then(|p| serde_json::from_str::(p).ok()); + let selection = package.map_or(PackageSelection::DefaultOrAll, PackageSelection::Selected); + match resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + ) { + Ok(workspace) => Some(workspace), + Err(err) => { + eprintln!("ERROR: Failed to resolve workspace: {err}"); + None + } + } +} + +fn workspace_not_found_error_msg(project_folder: &str, package: Option<&str>) -> String { + match package { + Some(pkg) => format!( + r#"Noir Debugger could not load program from {}, package {}"#, + project_folder, pkg + ), + None => format!(r#"Noir Debugger could not load program from {}"#, project_folder), + } +} + +fn load_and_compile_project( + project_folder: &str, + package: Option<&str>, + prover_name: &str, + expression_width: ExpressionWidth, + acir_mode: bool, + skip_instrumentation: bool, +) -> 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 + .into_iter() + .find(|p| p.is_binary()) + .ok_or(LoadError::Generic("No matching binary packages found in workspace".into()))?; + + let compiled_program = compile_bin_package_for_debugging( + &workspace, + package, + acir_mode, + skip_instrumentation, + CompileOptions::default(), + ) + .map_err(|_| LoadError::Generic("Failed to compile project".into()))?; + + let compiled_program = nargo::ops::transform_program(compiled_program, expression_width); + + let (inputs_map, _) = + read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &compiled_program.abi) + .map_err(|_| { + LoadError::Generic(format!("Failed to read program inputs from {}", prover_name)) + })?; + let initial_witness = compiled_program + .abi + .encode(&inputs_map, None) + .map_err(|_| LoadError::Generic("Failed to encode inputs".into()))?; + + Ok((compiled_program, initial_witness)) +} + +fn loop_uninitialized_dap( + mut server: Server, + expression_width: ExpressionWidth, + pedantic_solving: bool, +) -> Result<(), DapError> { + loop { + let req = match server.poll_request()? { + Some(req) => req, + None => break, + }; + + match req.command { + Command::Initialize(_) => { + let rsp = req.success(ResponseBody::Initialize(Capabilities { + supports_disassemble_request: Some(true), + supports_instruction_breakpoints: Some(true), + supports_stepping_granularity: Some(true), + ..Default::default() + })); + server.respond(rsp)?; + } + + Command::Launch(ref arguments) => { + let Some(Value::Object(ref additional_data)) = arguments.additional_data else { + server.respond(req.error("Missing launch arguments"))?; + continue; + }; + let Some(Value::String(ref project_folder)) = additional_data.get("projectFolder") + else { + server.respond(req.error("Missing project folder argument"))?; + continue; + }; + + let project_folder = project_folder.as_str(); + let package = additional_data.get("package").and_then(|v| v.as_str()); + let prover_name = additional_data + .get("proverName") + .and_then(|v| v.as_str()) + .unwrap_or(PROVER_INPUT_FILE); + + let generate_acir = + additional_data.get("generateAcir").and_then(|v| v.as_bool()).unwrap_or(false); + let skip_instrumentation = additional_data + .get("skipInstrumentation") + .and_then(|v| v.as_bool()) + .unwrap_or(generate_acir); + + eprintln!("Project folder: {}", project_folder); + eprintln!("Package: {}", package.unwrap_or("(default)")); + eprintln!("Prover name: {}", prover_name); + + match load_and_compile_project( + project_folder, + package, + prover_name, + expression_width, + generate_acir, + skip_instrumentation, + ) { + Ok((compiled_program, initial_witness)) => { + server.respond(req.ack()?)?; + + noir_debugger::run_dap_loop( + server, + &Bn254BlackBoxSolver(pedantic_solving), + compiled_program, + initial_witness, + )?; + break; + } + Err(LoadError::Generic(message)) => { + server.respond(req.error(message.as_str()))?; + } + } + } + + Command::Disconnect(_) => { + server.respond(req.ack()?)?; + break; + } + + _ => { + let command = req.command; + eprintln!("ERROR: unhandled command: {command:?}"); + } + } + } + Ok(()) +} + +fn run_preflight_check( + expression_width: ExpressionWidth, + args: DapCommand, +) -> Result<(), DapError> { + let project_folder = if let Some(project_folder) = args.preflight_project_folder { + project_folder + } else { + return Err(DapError::PreFlightGenericError("Noir Debugger could not initialize because the IDE (for example, VS Code) did not specify a project folder to debug.".into())); + }; + + let package = args.preflight_package.as_deref(); + let prover_name = args.preflight_prover_name.as_deref().unwrap_or(PROVER_INPUT_FILE); + + let _ = load_and_compile_project( + project_folder.as_str(), + package, + prover_name, + expression_width, + args.preflight_generate_acir, + args.preflight_skip_instrumentation, + )?; + + Ok(()) +} + +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. + // + // This lets the client IDE present any initialization issues (compiler version mismatches, missing prover files, etc) + // in its own interface. + // + // This was necessary due to the VS Code project being reluctant to let extension authors capture + // stderr output generated by a DAP server wrapped in DebugAdapterExecutable. + // + // Exposing this preflight mode lets us gracefully handle errors that happen *before* + // 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(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, args.expression_width, args.pedantic_solving) + .map_err(CliError::DapError) +} diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs new file mode 100644 index 00000000000..2ed30639d32 --- /dev/null +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -0,0 +1,251 @@ +use std::path::PathBuf; + +use acvm::acir::native_types::WitnessStack; +use acvm::FieldElement; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use clap::Args; + +use fm::FileManager; +use nargo::constants::PROVER_INPUT_FILE; +use nargo::errors::CompileError; +use nargo::ops::{compile_program, compile_program_with_debug_instrumenter, report_errors}; +use nargo::package::{CrateName, 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, InputValue}; +use noirc_abi::InputMap; +use noirc_driver::{ + file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, +}; +use noirc_frontend::debug::DebugInstrumenter; +use noirc_frontend::hir::ParsedFiles; + +use super::compile_cmd::get_target_width; +use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; +use super::NargoConfig; +use crate::errors::CliError; + +/// Executes a circuit in debug mode +#[derive(Debug, Clone, Args)] +pub(crate) struct DebugCommand { + /// Write the execution witness to named file + witness_name: Option, + + /// 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 package to execute + #[clap(long)] + pub(super) package: Option, + + #[clap(flatten)] + compile_options: CompileOptions, + + /// Force ACIR output (disabling instrumentation) + #[clap(long)] + acir_mode: bool, + + /// Disable vars debug instrumentation (enabled by default) + #[clap(long)] + skip_instrumentation: Option, +} + +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); + + let toml_path = get_package_manifest(&config.program_dir)?; + let selection = args.package.map_or(PackageSelection::DefaultOrAll, PackageSelection::Selected); + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; + let target_dir = &workspace.target_directory_path(); + + let Some(package) = workspace.into_iter().find(|p| p.is_binary()) else { + println!( + "No matching binary packages found in workspace. Only binary packages can be debugged." + ); + return Ok(()); + }; + + let compiled_program = compile_bin_package_for_debugging( + &workspace, + package, + acir_mode, + skip_instrumentation, + args.compile_options.clone(), + )?; + + let target_width = + get_target_width(package.expression_width, args.compile_options.expression_width); + + let compiled_program = nargo::ops::transform_program(compiled_program, target_width); + + run_async( + package, + compiled_program, + &args.prover_name, + &args.witness_name, + target_dir, + args.compile_options.pedantic_solving, + ) +} + +pub(crate) fn compile_bin_package_for_debugging( + workspace: &Workspace, + package: &Package, + acir_mode: bool, + skip_instrumentation: bool, + compile_options: CompileOptions, +) -> Result { + let mut workspace_file_manager = file_manager_with_stdlib(std::path::Path::new("")); + insert_all_files_for_workspace_into_file_manager(workspace, &mut workspace_file_manager); + let mut parsed_files = parse_all(&workspace_file_manager); + + let compile_options = CompileOptions { + instrument_debug: !skip_instrumentation, + force_brillig: !acir_mode, + ..compile_options + }; + + let compilation_result = if !skip_instrumentation { + let debug_state = + instrument_package_files(&mut parsed_files, &workspace_file_manager, package); + + compile_program_with_debug_instrumenter( + &workspace_file_manager, + &parsed_files, + workspace, + package, + &compile_options, + None, + debug_state, + ) + } else { + compile_program( + &workspace_file_manager, + &parsed_files, + workspace, + package, + &compile_options, + None, + ) + }; + + report_errors( + compilation_result, + &workspace_file_manager, + compile_options.deny_warnings, + compile_options.silence_warnings, + ) +} + +/// Add debugging instrumentation to all parsed files belonging to the package +/// being compiled +fn instrument_package_files( + parsed_files: &mut ParsedFiles, + file_manager: &FileManager, + package: &Package, +) -> DebugInstrumenter { + // Start off at the entry path and read all files in the parent directory. + let entry_path_parent = package + .entry_path + .parent() + .unwrap_or_else(|| panic!("The entry path is expected to be a single file within a directory and so should have a parent {:?}", package.entry_path)); + + let mut debug_instrumenter = DebugInstrumenter::default(); + + for (file_id, parsed_file) in parsed_files.iter_mut() { + let file_path = + file_manager.path(*file_id).expect("Parsed file ID not found in file manager"); + for ancestor in file_path.ancestors() { + if ancestor == entry_path_parent { + // file is in package + debug_instrumenter.instrument_module(&mut parsed_file.0); + } + } + } + + debug_instrumenter +} + +fn run_async( + package: &Package, + program: CompiledProgram, + prover_name: &str, + witness_name: &Option, + target_dir: &PathBuf, + pedantic_solving: bool, +) -> Result<(), CliError> { + use tokio::runtime::Builder; + let runtime = Builder::new_current_thread().enable_all().build().unwrap(); + + runtime.block_on(async { + println!("[{}] Starting debugger", package.name); + let (return_value, witness_stack) = + debug_program_and_decode(program, package, prover_name, pedantic_solving)?; + + if let Some(solved_witness_stack) = witness_stack { + println!("[{}] Circuit witness successfully solved", package.name); + + if let Some(return_value) = return_value { + println!("[{}] Circuit output: {return_value:?}", package.name); + } + + if let Some(witness_name) = witness_name { + let witness_path = + save_witness_to_dir(solved_witness_stack, witness_name, target_dir)?; + + println!("[{}] Witness saved to {}", package.name, witness_path.display()); + } + } else { + println!("Debugger execution halted."); + } + + Ok(()) + }) +} + +fn debug_program_and_decode( + program: CompiledProgram, + package: &Package, + prover_name: &str, + pedantic_solving: bool, +) -> 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)?; + let program_abi = program.abi.clone(); + let witness_stack = debug_program(program, &inputs_map, pedantic_solving)?; + + match witness_stack { + Some(witness_stack) => { + let main_witness = &witness_stack + .peek() + .expect("Should have at least one witness on the stack") + .witness; + let (_, return_value) = program_abi.decode(main_witness)?; + Ok((return_value, Some(witness_stack))) + } + None => Ok((None, None)), + } +} + +pub(crate) fn debug_program( + compiled_program: CompiledProgram, + inputs_map: &InputMap, + pedantic_solving: bool, +) -> Result>, CliError> { + let initial_witness = compiled_program.abi.encode(inputs_map, None)?; + + noir_debugger::run_repl_session( + &Bn254BlackBoxSolver(pedantic_solving), + compiled_program, + initial_witness, + ) + .map_err(CliError::from) +} diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs new file mode 100644 index 00000000000..cb471995be5 --- /dev/null +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -0,0 +1,179 @@ +use std::path::PathBuf; + +use acvm::acir::native_types::WitnessStack; +use acvm::FieldElement; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use clap::Args; + +use nargo::constants::PROVER_INPUT_FILE; +use nargo::errors::try_to_diagnose_runtime_error; +use nargo::foreign_calls::DefaultForeignCallBuilder; +use nargo::package::Package; +use nargo::PrintOutput; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; +use noirc_abi::input_parser::{Format, InputValue}; +use noirc_abi::InputMap; +use noirc_artifacts::debug::DebugArtifact; +use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; + +use super::compile_cmd::compile_workspace_full; +use super::fs::{inputs::read_inputs_from_file, witness::save_witness_to_dir}; +use super::{NargoConfig, PackageOptions}; +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 + /// + /// Defaults to the name of the package being executed. + witness_name: Option, + + /// The name of the toml file which contains the inputs for the prover + #[clap(long, short, default_value = PROVER_INPUT_FILE)] + prover_name: String, + + #[clap(flatten)] + pub(super) package_options: PackageOptions, + + #[clap(flatten)] + compile_options: CompileOptions, + + /// JSON RPC url to solve oracle calls + #[clap(long)] + oracle_resolver: Option, +} + +pub(crate) fn run(args: ExecuteCommand, config: NargoConfig) -> Result<(), CliError> { + let toml_path = get_package_manifest(&config.program_dir)?; + let selection = args.package_options.package_selection(); + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; + let target_dir = &workspace.target_directory_path(); + + // Compile the full workspace in order to generate any build artifacts. + compile_workspace_full(&workspace, &args.compile_options)?; + + let binary_packages = workspace.into_iter().filter(|package| package.is_binary()); + for package in binary_packages { + let program_artifact_path = workspace.package_build_path(package); + let program: CompiledProgram = + read_program_from_file(program_artifact_path.clone())?.into(); + let abi = program.abi.clone(); + + let results = execute_program_and_decode( + program, + package, + &args.prover_name, + args.oracle_resolver.as_deref(), + Some(workspace.root_dir.clone()), + Some(package.name.to_string()), + args.compile_options.pedantic_solving, + )?; + + println!("[{}] Circuit witness successfully solved", package.name); + if let Some(ref return_value) = results.actual_return { + println!("[{}] Circuit output: {return_value:?}", package.name); + } + + let package_name = package.name.clone().into(); + let witness_name = args.witness_name.as_ref().unwrap_or(&package_name); + let witness_path = save_witness_to_dir(results.witness_stack, witness_name, target_dir)?; + println!("[{}] Witness saved to {}", package.name, witness_path.display()); + + // Sanity checks on the return value after the witness has been saved, so it can be inspected if necessary. + if let Some(expected) = results.expected_return { + if results.actual_return.as_ref() != Some(&expected) { + return Err(CliError::UnexpectedReturn { expected, actual: results.actual_return }); + } + } + // We can expect that if the circuit returns something, it should be non-empty after execution. + if let Some(ref expected) = abi.return_type { + if results.actual_return.is_none() { + return Err(CliError::MissingReturn { expected: expected.clone() }); + } + } + } + Ok(()) +} + +fn execute_program_and_decode( + program: CompiledProgram, + package: &Package, + prover_name: &str, + foreign_call_resolver_url: Option<&str>, + root_path: Option, + package_name: Option, + pedantic_solving: bool, +) -> Result { + // Parse the initial witness values from Prover.toml + let (inputs_map, expected_return) = + read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?; + let witness_stack = execute_program( + &program, + &inputs_map, + foreign_call_resolver_url, + root_path, + package_name, + pedantic_solving, + )?; + // 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 (_, actual_return) = program.abi.decode(main_witness)?; + + Ok(ExecutionResults { expected_return, actual_return, witness_stack }) +} + +struct ExecutionResults { + expected_return: Option, + actual_return: Option, + witness_stack: WitnessStack, +} + +pub(crate) fn execute_program( + compiled_program: &CompiledProgram, + inputs_map: &InputMap, + foreign_call_resolver_url: Option<&str>, + root_path: Option, + package_name: Option, + pedantic_solving: bool, +) -> Result, CliError> { + let initial_witness = compiled_program.abi.encode(inputs_map, None)?; + + let solved_witness_stack_err = nargo::ops::execute_program( + &compiled_program.program, + initial_witness, + &Bn254BlackBoxSolver(pedantic_solving), + &mut DefaultForeignCallBuilder { + output: PrintOutput::Stdout, + enable_mocks: false, + resolver_url: foreign_call_resolver_url.map(|s| s.to_string()), + root_path, + package_name, + } + .build(), + ); + match solved_witness_stack_err { + Ok(solved_witness_stack) => Ok(solved_witness_stack), + Err(err) => { + let debug_artifact = DebugArtifact { + debug_symbols: compiled_program.debug.clone(), + file_map: compiled_program.file_map.clone(), + }; + + if let Some(diagnostic) = + try_to_diagnose_runtime_error(&err, &compiled_program.abi, &compiled_program.debug) + { + diagnostic.report(&debug_artifact, false); + } + + Err(CliError::NargoError(err)) + } + } +} diff --git a/tooling/nargo_cli/src/cli/export_cmd.rs b/tooling/nargo_cli/src/cli/export_cmd.rs new file mode 100644 index 00000000000..cb92b987c4e --- /dev/null +++ b/tooling/nargo_cli/src/cli/export_cmd.rs @@ -0,0 +1,102 @@ +use nargo::errors::CompileError; +use nargo::ops::report_errors; +use noirc_errors::FileDiagnostic; +use noirc_frontend::hir::ParsedFiles; +use rayon::prelude::*; + +use fm::FileManager; +use iter_extended::try_vecmap; +use nargo::package::Package; +use nargo::prepare_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}; +use noirc_driver::{ + compile_no_check, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, +}; + +use clap::Args; + +use crate::errors::CliError; + +use super::check_cmd::check_crate_and_report_errors; + +use super::fs::program::save_program_to_file; +use super::{NargoConfig, PackageOptions}; + +/// Exports functions marked with #[export] attribute +#[derive(Debug, Clone, Args)] +pub(crate) struct ExportCommand { + #[clap(flatten)] + pub(super) package_options: PackageOptions, + + #[clap(flatten)] + compile_options: CompileOptions, +} + +pub(crate) fn run(args: ExportCommand, config: NargoConfig) -> Result<(), CliError> { + let toml_path = get_package_manifest(&config.program_dir)?; + let selection = args.package_options.package_selection(); + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_owned()), + )?; + + let mut workspace_file_manager = workspace.new_file_manager(); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let parsed_files = parse_all(&workspace_file_manager); + + let library_packages: Vec<_> = + workspace.into_iter().filter(|package| package.is_library()).collect(); + + library_packages + .par_iter() + .map(|package| { + compile_exported_functions( + &workspace_file_manager, + &parsed_files, + &workspace, + package, + &args.compile_options, + ) + }) + .collect() +} + +fn compile_exported_functions( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + workspace: &Workspace, + package: &Package, + compile_options: &CompileOptions, +) -> Result<(), CliError> { + let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package); + check_crate_and_report_errors(&mut context, crate_id, compile_options)?; + + let exported_functions = context.get_all_exported_functions_in_crate(&crate_id); + + let exported_programs = try_vecmap( + exported_functions, + |(function_name, function_id)| -> Result<(String, CompiledProgram), CompileError> { + // TODO: We should to refactor how to deal with compilation errors to avoid this. + let program = compile_no_check(&mut context, compile_options, function_id, None, false) + .map_err(|error| vec![FileDiagnostic::from(error)]); + + let program = report_errors( + program.map(|program| (program, Vec::new())), + file_manager, + compile_options.deny_warnings, + compile_options.silence_warnings, + )?; + + Ok((function_name, program)) + }, + )?; + + let export_dir = workspace.export_directory_path(); + for (function_name, program) in exported_programs { + save_program_to_file(&program.into(), &function_name.parse().unwrap(), &export_dir); + } + Ok(()) +} diff --git a/tooling/nargo_cli/src/cli/fmt_cmd.rs b/tooling/nargo_cli/src/cli/fmt_cmd.rs new file mode 100644 index 00000000000..7b29a90c5c0 --- /dev/null +++ b/tooling/nargo_cli/src/cli/fmt_cmd.rs @@ -0,0 +1,125 @@ +use std::{fs::DirEntry, path::Path}; + +use clap::Args; +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::NOIR_ARTIFACT_VERSION_STRING; +use noirc_errors::CustomDiagnostic; +use noirc_frontend::{hir::def_map::parse_file, parser::ParserError}; + +use crate::errors::CliError; + +use super::{NargoConfig, PackageOptions}; + +/// Format the Noir files in a workspace +#[derive(Debug, Clone, Args)] +pub(crate) struct FormatCommand { + /// Run noirfmt in check mode + #[arg(long)] + check: bool, + + #[clap(flatten)] + pub(super) package_options: PackageOptions, +} + +pub(crate) fn run(args: FormatCommand, config: NargoConfig) -> Result<(), CliError> { + let check_mode = args.check; + + let toml_path = get_package_manifest(&config.program_dir)?; + let selection = match args.package_options.package_selection() { + PackageSelection::DefaultOrAll => PackageSelection::All, + other => other, + }; + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; + + let mut workspace_file_manager = workspace.new_file_manager(); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + + let config = nargo_fmt::Config::read(&config.program_dir) + .map_err(|err| CliError::Generic(err.to_string()))?; + + let mut check_exit_code_one = false; + + for package in &workspace { + visit_noir_files(&package.root_dir.join("src"), &mut |entry| { + let file_id = workspace_file_manager.name_to_id(entry.path().to_path_buf()).expect("The file should exist since we added all files in the package into the file manager"); + + let (parsed_module, errors) = parse_file(&workspace_file_manager, file_id); + + let is_all_warnings = errors.iter().all(ParserError::is_warning); + if !is_all_warnings { + let errors = errors + .into_iter() + .map(|error| { + let error = CustomDiagnostic::from(&error); + error.in_file(file_id) + }) + .collect(); + + let _ = report_errors::<()>( + Err(errors), + &workspace_file_manager, + false, + false, + ); + return Ok(()); + } + + let original = workspace_file_manager.fetch_file(file_id).expect("The file should exist since we added all files in the package into the file manager"); + let formatted = nargo_fmt::format(original, parsed_module, &config); + + if check_mode { + let diff = similar_asserts::SimpleDiff::from_str( + original, + &formatted, + "original", + "formatted", + ) + .to_string(); + + if !diff.lines().next().is_some_and(|line| line.contains("Invisible differences")) { + if !check_exit_code_one { + check_exit_code_one = true; + } + + println!("{diff}"); + } + + Ok(()) + } else { + std::fs::write(entry.path(), formatted) + } + }) + .map_err(|error| CliError::Generic(error.to_string()))?; + } + + if check_exit_code_one { + std::process::exit(1); + } else if check_mode { + println!("No formatting changes were detected"); + } + + Ok(()) +} + +fn visit_noir_files( + dir: &Path, + cb: &mut dyn FnMut(&DirEntry) -> std::io::Result<()>, +) -> std::io::Result<()> { + if dir.is_dir() { + for entry in std::fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + visit_noir_files(&path, cb)?; + } else if entry.path().extension().map_or(false, |extension| extension == "nr") { + cb(&entry)?; + } + } + } + Ok(()) +} diff --git a/tooling/nargo_cli/src/cli/fs/inputs.rs b/tooling/nargo_cli/src/cli/fs/inputs.rs new file mode 100644 index 00000000000..4a7a81431bb --- /dev/null +++ b/tooling/nargo_cli/src/cli/fs/inputs.rs @@ -0,0 +1,42 @@ +use noirc_abi::{ + input_parser::{Format, InputValue}, + Abi, InputMap, MAIN_RETURN_NAME, +}; +use std::{collections::BTreeMap, path::Path}; + +use crate::errors::FilesystemError; + +/// Returns the circuit's parameters and its return value, if one exists. +/// # Examples +/// +/// ```ignore +/// let (input_map, return_value): (InputMap, Option) = +/// read_inputs_from_file(path, "Verifier", Format::Toml, &abi)?; +/// ``` +pub(crate) fn read_inputs_from_file>( + path: P, + file_name: &str, + format: Format, + abi: &Abi, +) -> Result<(InputMap, Option), FilesystemError> { + if abi.is_empty() { + return Ok((BTreeMap::new(), None)); + } + + let file_path = path.as_ref().join(file_name).with_extension(format.ext()); + if !file_path.exists() { + if abi.parameters.is_empty() { + // Reading a return value from the `Prover.toml` is optional, + // so if the ABI has no parameters we can skip reading the file if it doesn't exist. + return Ok((BTreeMap::new(), None)); + } else { + return Err(FilesystemError::MissingTomlFile(file_name.to_owned(), file_path)); + } + } + + let input_string = std::fs::read_to_string(file_path).unwrap(); + let mut input_map = format.parse(&input_string, abi)?; + let return_value = input_map.remove(MAIN_RETURN_NAME); + + Ok((input_map, return_value)) +} diff --git a/tooling/nargo_cli/src/cli/fs/mod.rs b/tooling/nargo_cli/src/cli/fs/mod.rs new file mode 100644 index 00000000000..8658bd5b248 --- /dev/null +++ b/tooling/nargo_cli/src/cli/fs/mod.rs @@ -0,0 +1,30 @@ +use std::{ + fs::File, + io::Write, + path::{Path, PathBuf}, +}; + +pub(super) mod inputs; +pub(super) mod program; +pub(super) mod witness; + +pub(super) 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) +} + +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/nargo_cli/src/cli/fs/program.rs b/tooling/nargo_cli/src/cli/fs/program.rs new file mode 100644 index 00000000000..87783e4573a --- /dev/null +++ b/tooling/nargo_cli/src/cli/fs/program.rs @@ -0,0 +1,51 @@ +use std::path::{Path, PathBuf}; + +use nargo::package::CrateName; +use noirc_artifacts::{contract::ContractArtifact, program::ProgramArtifact}; + +use crate::errors::FilesystemError; + +use super::{create_named_dir, write_to_file}; + +pub(crate) fn save_program_to_file>( + program_artifact: &ProgramArtifact, + crate_name: &CrateName, + circuit_dir: P, +) -> PathBuf { + let circuit_name: String = crate_name.into(); + save_build_artifact_to_file(program_artifact, &circuit_name, circuit_dir) +} + +pub(crate) fn save_contract_to_file>( + compiled_contract: &ContractArtifact, + circuit_name: &str, + circuit_dir: P, +) -> PathBuf { + save_build_artifact_to_file(compiled_contract, circuit_name, circuit_dir) +} + +fn save_build_artifact_to_file, T: ?Sized + serde::Serialize>( + build_artifact: &T, + artifact_name: &str, + circuit_dir: P, +) -> PathBuf { + create_named_dir(circuit_dir.as_ref(), "target"); + let circuit_path = circuit_dir.as_ref().join(artifact_name).with_extension("json"); + write_to_file(&serde_json::to_vec(build_artifact).unwrap(), &circuit_path); + + circuit_path +} + +#[tracing::instrument(level = "trace", skip_all)] +pub(crate) fn read_program_from_file>( + circuit_path: P, +) -> Result { + let file_path = circuit_path.as_ref().with_extension("json"); + + let input_string = + std::fs::read(&file_path).map_err(|_| FilesystemError::PathNotValid(file_path))?; + let program = serde_json::from_slice(&input_string) + .map_err(|err| FilesystemError::ProgramSerializationError(err.to_string()))?; + + Ok(program) +} diff --git a/tooling/nargo_cli/src/cli/fs/witness.rs b/tooling/nargo_cli/src/cli/fs/witness.rs new file mode 100644 index 00000000000..f95eb3d7a4c --- /dev/null +++ b/tooling/nargo_cli/src/cli/fs/witness.rs @@ -0,0 +1,22 @@ +use std::path::{Path, PathBuf}; + +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>( + 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 = witness_stack.try_into()?; + + write_to_file(buf.as_slice(), &witness_path); + + Ok(witness_path) +} diff --git a/tooling/nargo_cli/src/cli/generate_completion_script_cmd.rs b/tooling/nargo_cli/src/cli/generate_completion_script_cmd.rs new file mode 100644 index 00000000000..0b8fa1ee3e7 --- /dev/null +++ b/tooling/nargo_cli/src/cli/generate_completion_script_cmd.rs @@ -0,0 +1,33 @@ +use clap::{Args, CommandFactory}; +use clap_complete::Shell; + +use crate::errors::CliError; + +use super::NargoCli; + +/// Generates a shell completion script for your favorite shell +#[derive(Debug, Clone, Args)] +pub(crate) struct GenerateCompletionScriptCommand { + /// The shell to generate completions for. One of: bash, elvish, fish, powershell, zsh + pub(crate) shell: String, +} + +pub(crate) fn run(command: GenerateCompletionScriptCommand) -> Result<(), CliError> { + let shell = match command.shell.to_lowercase().as_str() { + "bash" => Shell::Bash, + "elvish" => Shell::Elvish, + "fish" => Shell::Fish, + "powershell" => Shell::PowerShell, + "zsh" => Shell::Zsh, + _ => { + return Err(CliError::Generic( + "Invalid shell. Supported shells are: bash, elvish, fish, powershell, zsh" + .to_string(), + )) + } + }; + + clap_complete::generate(shell, &mut NargoCli::command(), "nargo", &mut std::io::stdout()); + + Ok(()) +} diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs new file mode 100644 index 00000000000..8d0fc257e1c --- /dev/null +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -0,0 +1,283 @@ +use acvm::acir::circuit::ExpressionWidth; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use clap::Args; +use iter_extended::vecmap; +use nargo::{ + constants::PROVER_INPUT_FILE, foreign_calls::DefaultForeignCallBuilder, package::Package, +}; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; +use noirc_abi::input_parser::Format; +use noirc_artifacts::program::ProgramArtifact; +use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; +use prettytable::{row, table, Row}; +use rayon::prelude::*; +use serde::Serialize; + +use crate::{cli::fs::inputs::read_inputs_from_file, errors::CliError}; + +use super::{ + compile_cmd::{compile_workspace_full, get_target_width}, + fs::program::read_program_from_file, + NargoConfig, PackageOptions, +}; + +/// 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 +#[derive(Debug, Clone, Args)] +#[clap(visible_alias = "i")] +pub(crate) struct InfoCommand { + #[clap(flatten)] + pub(super) package_options: PackageOptions, + + /// Output a JSON formatted report. Changes to this format are not currently considered breaking. + #[clap(long, hide = true)] + json: bool, + + #[clap(long)] + profile_execution: bool, + + /// The name of the toml file which contains the inputs for the prover + #[clap(long, short, default_value = PROVER_INPUT_FILE)] + prover_name: String, + + #[clap(flatten)] + compile_options: CompileOptions, +} + +pub(crate) fn run(mut args: InfoCommand, config: NargoConfig) -> Result<(), CliError> { + let toml_path = get_package_manifest(&config.program_dir)?; + let selection = args.package_options.package_selection(); + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; + + if args.profile_execution { + // Execution profiling is only relevant with the Brillig VM + // as a constrained circuit should have totally flattened control flow (e.g. loops and if statements). + args.compile_options.force_brillig = true; + } + // Compile the full workspace in order to generate any build artifacts. + compile_workspace_full(&workspace, &args.compile_options)?; + + 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::>()?; + + let program_info = if args.profile_execution { + assert!( + args.compile_options.force_brillig, + "Internal CLI Error: --force-brillig must be active when --profile-execution is active" + ); + profile_brillig_execution( + binary_packages, + &args.prover_name, + args.compile_options.expression_width, + args.compile_options.pedantic_solving, + )? + } else { + binary_packages + .into_iter() + .par_bridge() + .map(|(package, program)| { + let target_width = get_target_width( + package.expression_width, + args.compile_options.expression_width, + ); + count_opcodes_and_gates_in_program(program, &package, target_width) + }) + .collect() + }; + + let info_report = InfoReport { programs: program_info }; + + if args.json { + // Expose machine-readable JSON data. + println!("{}", serde_json::to_string(&info_report).unwrap()); + } else { + // Otherwise print human-readable table. + if !info_report.programs.is_empty() { + let mut program_table = table!([Fm->"Package", Fm->"Function", Fm->"Expression Width", Fm->"ACIR Opcodes", Fm->"Brillig Opcodes"]); + + for program_info in info_report.programs { + let program_rows: Vec = program_info.into(); + for row in program_rows { + program_table.add_row(row); + } + } + program_table.printstd(); + } + } + + Ok(()) +} + +#[derive(Debug, Default, Serialize)] +struct InfoReport { + programs: Vec, +} + +#[derive(Debug, Serialize)] +struct ProgramInfo { + package_name: String, + #[serde(skip)] + expression_width: ExpressionWidth, + functions: Vec, + #[serde(skip)] + unconstrained_functions_opcodes: usize, + unconstrained_functions: Vec, +} + +impl From for Vec { + fn from(program_info: ProgramInfo) -> Self { + let mut main = vecmap(program_info.functions, |function| { + row![ + Fm->format!("{}", program_info.package_name), + Fc->format!("{}", function.name), + format!("{:?}", program_info.expression_width), + Fc->format!("{}", function.opcodes), + Fc->format!("{}", program_info.unconstrained_functions_opcodes), + ] + }); + main.extend(vecmap(program_info.unconstrained_functions, |function| { + row![ + Fm->format!("{}", program_info.package_name), + Fc->format!("{}", function.name), + format!("N/A", ), + Fc->format!("N/A"), + Fc->format!("{}", function.opcodes), + ] + })); + main + } +} + +#[derive(Debug, Serialize)] +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, +} + +#[derive(Debug, Serialize)] +struct FunctionInfo { + name: String, + opcodes: usize, +} + +impl From for Vec { + fn from(contract_info: ContractInfo) -> Self { + vecmap(contract_info.functions, |function| { + row![ + Fm->format!("{}", contract_info.name), + Fc->format!("{}", function.name), + format!("{:?}", contract_info.expression_width), + Fc->format!("{}", function.opcodes), + ] + }) + } +} + +fn count_opcodes_and_gates_in_program( + compiled_program: ProgramArtifact, + package: &Package, + expression_width: ExpressionWidth, +) -> ProgramInfo { + let functions = compiled_program + .bytecode + .functions + .into_par_iter() + .enumerate() + .map(|(i, function)| FunctionInfo { + name: compiled_program.names[i].clone(), + opcodes: function.opcodes.len(), + }) + .collect(); + + let opcodes_len: Vec = compiled_program + .bytecode + .unconstrained_functions + .iter() + .map(|func| func.bytecode.len()) + .collect(); + let unconstrained_functions_opcodes = compiled_program + .bytecode + .unconstrained_functions + .into_par_iter() + .map(|function| function.bytecode.len()) + .sum(); + let unconstrained_info: Vec = compiled_program + .brillig_names + .clone() + .iter() + .zip(opcodes_len) + .map(|(name, len)| FunctionInfo { name: name.clone(), opcodes: len }) + .collect(); + + ProgramInfo { + package_name: package.name.to_string(), + expression_width, + functions, + unconstrained_functions_opcodes, + unconstrained_functions: unconstrained_info, + } +} + +fn profile_brillig_execution( + binary_packages: Vec<(Package, ProgramArtifact)>, + prover_name: &str, + expression_width: Option, + pedantic_solving: bool, +) -> Result, CliError> { + let mut program_info = Vec::new(); + for (package, program_artifact) in binary_packages.iter() { + // Parse the initial witness values from Prover.toml + let (inputs_map, _) = read_inputs_from_file( + &package.root_dir, + prover_name, + Format::Toml, + &program_artifact.abi, + )?; + let initial_witness = program_artifact.abi.encode(&inputs_map, None)?; + + let (_, profiling_samples) = nargo::ops::execute_program_with_profiling( + &program_artifact.bytecode, + initial_witness, + &Bn254BlackBoxSolver(pedantic_solving), + &mut DefaultForeignCallBuilder::default().build(), + ) + .map_err(|e| { + CliError::Generic(format!( + "failed to execute '{}': {}", + package.root_dir.to_string_lossy(), + e + )) + })?; + + let expression_width = get_target_width(package.expression_width, expression_width); + + program_info.push(ProgramInfo { + package_name: package.name.to_string(), + expression_width, + functions: vec![FunctionInfo { name: "main".to_string(), opcodes: 0 }], + unconstrained_functions_opcodes: profiling_samples.len(), + unconstrained_functions: vec![FunctionInfo { + name: "main".to_string(), + opcodes: profiling_samples.len(), + }], + }); + } + Ok(program_info) +} diff --git a/tooling/nargo_cli/src/cli/init_cmd.rs b/tooling/nargo_cli/src/cli/init_cmd.rs new file mode 100644 index 00000000000..ffeb5d9ba74 --- /dev/null +++ b/tooling/nargo_cli/src/cli/init_cmd.rs @@ -0,0 +1,82 @@ +use crate::errors::CliError; + +use super::fs::{create_named_dir, write_to_file}; +use super::NargoConfig; +use clap::Args; +use nargo::constants::{PKG_FILE, SRC_DIR}; +use nargo::package::{CrateName, PackageType}; +use std::path::PathBuf; + +/// Create a Noir project in the current directory. +#[derive(Debug, Clone, Args)] +pub(crate) struct InitCommand { + /// Name of the package [default: current directory name] + #[clap(long)] + name: Option, + + /// Use a library template + #[arg(long, conflicts_with = "bin", conflicts_with = "contract")] + pub(crate) lib: bool, + + /// Use a binary template [default] + #[arg(long, conflicts_with = "lib", conflicts_with = "contract")] + pub(crate) bin: bool, + + /// Use a contract template + #[arg(long, conflicts_with = "lib", conflicts_with = "bin")] + pub(crate) contract: bool, +} + +const BIN_EXAMPLE: &str = include_str!("./noir_template_files/binary.nr"); +const CONTRACT_EXAMPLE: &str = include_str!("./noir_template_files/contract.nr"); +const LIB_EXAMPLE: &str = include_str!("./noir_template_files/library.nr"); + +pub(crate) fn run(args: InitCommand, config: NargoConfig) -> Result<(), CliError> { + let package_name = match args.name { + Some(name) => name, + None => { + let name = config.program_dir.file_name().unwrap().to_str().unwrap(); + name.parse().map_err(|_| CliError::InvalidPackageName(name.into()))? + } + }; + + let package_type = if args.lib { + PackageType::Library + } else if args.contract { + PackageType::Contract + } else { + PackageType::Binary + }; + initialize_project(config.program_dir, package_name, package_type); + Ok(()) +} + +/// Initializes a new Noir project in `package_dir`. +pub(crate) fn initialize_project( + package_dir: PathBuf, + package_name: CrateName, + package_type: PackageType, +) { + let src_dir = package_dir.join(SRC_DIR); + create_named_dir(&src_dir, "src"); + + let toml_contents = format!( + r#"[package] +name = "{package_name}" +type = "{package_type}" +authors = [""] + +[dependencies]"# + ); + + write_to_file(toml_contents.as_bytes(), &package_dir.join(PKG_FILE)); + // This uses the `match` syntax instead of `if` so we get a compile error when we add new package types (which likely need new template files) + match package_type { + PackageType::Binary => write_to_file(BIN_EXAMPLE.as_bytes(), &src_dir.join("main.nr")), + PackageType::Contract => { + write_to_file(CONTRACT_EXAMPLE.as_bytes(), &src_dir.join("main.nr")) + } + PackageType::Library => write_to_file(LIB_EXAMPLE.as_bytes(), &src_dir.join("lib.nr")), + }; + println!("Project successfully created! It is located at {}", package_dir.display()); +} diff --git a/tooling/nargo_cli/src/cli/lsp_cmd.rs b/tooling/nargo_cli/src/cli/lsp_cmd.rs new file mode 100644 index 00000000000..dc5d0995c06 --- /dev/null +++ b/tooling/nargo_cli/src/cli/lsp_cmd.rs @@ -0,0 +1,54 @@ +use async_lsp::{ + concurrency::ConcurrencyLayer, panic::CatchUnwindLayer, server::LifecycleLayer, + tracing::TracingLayer, +}; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use clap::Args; +use noir_lsp::NargoLspService; +use tower::ServiceBuilder; + +use super::NargoConfig; +use crate::errors::CliError; + +/// 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 +#[derive(Debug, Clone, Args)] +pub(crate) struct LspCommand; + +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 pedantic_solving = true; + let router = NargoLspService::new(&client, Bn254BlackBoxSolver(pedantic_solving)); + + ServiceBuilder::new() + .layer(TracingLayer::default()) + .layer(LifecycleLayer::default()) + .layer(CatchUnwindLayer::default()) + .layer(ConcurrencyLayer::default()) + .service(router) + }); + + // Prefer truly asynchronous piped stdin/stdout without blocking tasks. + #[cfg(unix)] + let (stdin, stdout) = ( + async_lsp::stdio::PipeStdin::lock_tokio().unwrap(), + async_lsp::stdio::PipeStdout::lock_tokio().unwrap(), + ); + // Fallback to spawn blocking read/write otherwise. + #[cfg(not(unix))] + let (stdin, stdout) = ( + tokio_util::compat::TokioAsyncReadCompatExt::compat(tokio::io::stdin()), + tokio_util::compat::TokioAsyncWriteCompatExt::compat_write(tokio::io::stdout()), + ); + + server.run_buffered(stdin, stdout).await.map_err(CliError::LspError) + }) +} diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs new file mode 100644 index 00000000000..0b725afcf4e --- /dev/null +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -0,0 +1,258 @@ +use clap::{Args, Parser, Subcommand}; +use const_format::formatcp; +use nargo_toml::{ManifestError, PackageSelection}; +use noirc_driver::{CrateName, NOIR_ARTIFACT_VERSION_STRING}; +use std::path::{Path, PathBuf}; + +use color_eyre::eyre; + +mod fs; + +mod check_cmd; +mod compile_cmd; +mod dap_cmd; +mod debug_cmd; +mod execute_cmd; +mod export_cmd; +mod fmt_cmd; +mod generate_completion_script_cmd; +mod info_cmd; +mod init_cmd; +mod lsp_cmd; +mod new_cmd; +mod test_cmd; + +const GIT_HASH: &str = env!("GIT_COMMIT"); +const IS_DIRTY: &str = env!("GIT_DIRTY"); +const NARGO_VERSION: &str = env!("CARGO_PKG_VERSION"); + +static VERSION_STRING: &str = formatcp!( + "version = {}\nnoirc version = {}\n(git version hash: {}, is dirty: {})", + NARGO_VERSION, + NOIR_ARTIFACT_VERSION_STRING, + GIT_HASH, + IS_DIRTY +); + +#[derive(Parser, Debug)] +#[command(name="nargo", author, version=VERSION_STRING, about, long_about = None)] +struct NargoCli { + #[command(subcommand)] + command: NargoCommand, + + #[clap(flatten)] + config: NargoConfig, +} + +#[non_exhaustive] +#[derive(Args, Clone, Debug)] +pub(crate) struct NargoConfig { + // REMINDER: Also change this flag in the LSP test lens if renamed + #[arg(long, hide = true, global = true, default_value = "./")] + program_dir: PathBuf, +} + +/// Options for commands that work on either workspace or package scope. +#[derive(Args, Clone, Debug, Default)] +pub(crate) struct PackageOptions { + /// The name of the package to run the command on. + /// By default run on the first one found moving up along the ancestors of the current directory. + #[clap(long, conflicts_with = "workspace")] + package: Option, + + /// Run on all packages in the workspace + #[clap(long, conflicts_with = "package")] + workspace: bool, +} + +impl PackageOptions { + /// Decide which package to run the command on: + /// * `package` if non-empty + /// * all packages if `workspace` is `true` + /// * otherwise the default package + pub(crate) fn package_selection(&self) -> PackageSelection { + let default_selection = + if self.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; + + self.package.clone().map_or(default_selection, PackageSelection::Selected) + } + + /// Whether we need to look for the package manifest at the workspace level. + /// If a package is specified, it might not be the current package. + fn scope(&self) -> CommandScope { + if self.workspace || self.package.is_some() { + CommandScope::Workspace + } else { + CommandScope::CurrentPackage + } + } +} + +enum CommandScope { + Workspace, + CurrentPackage, + Any, +} + +#[non_exhaustive] +#[derive(Subcommand, Clone, Debug)] +enum NargoCommand { + Check(check_cmd::CheckCommand), + Fmt(fmt_cmd::FormatCommand), + #[command(alias = "build")] + Compile(compile_cmd::CompileCommand), + New(new_cmd::NewCommand), + Init(init_cmd::InitCommand), + Execute(execute_cmd::ExecuteCommand), + #[command(hide = true)] // Hidden while the feature is being built out + Export(export_cmd::ExportCommand), + Debug(debug_cmd::DebugCommand), + Test(test_cmd::TestCommand), + Info(info_cmd::InfoCommand), + Lsp(lsp_cmd::LspCommand), + #[command(hide = true)] + Dap(dap_cmd::DapCommand), + GenerateCompletionScript(generate_completion_script_cmd::GenerateCompletionScriptCommand), +} + +#[cfg(not(feature = "codegen-docs"))] +#[tracing::instrument(level = "trace")] +pub(crate) fn start_cli() -> eyre::Result<()> { + use std::fs::File; + + use fs2::FileExt as _; + use nargo_toml::get_package_manifest; + + let NargoCli { command, mut config } = NargoCli::parse(); + + // If the provided `program_dir` is relative, make it absolute by joining it to the current directory. + if !config.program_dir.is_absolute() { + config.program_dir = std::env::current_dir().unwrap().join(config.program_dir); + } + + // Search through parent directories to find package root if necessary. + if let Some(program_dir) = command_dir(&command, &config.program_dir)? { + config.program_dir = program_dir; + } + + let lock_file = match needs_lock(&command) { + Some(exclusive) => { + let toml_path = get_package_manifest(&config.program_dir)?; + let file = File::open(toml_path).expect("Expected Nargo.toml to exist"); + if exclusive { + if file.try_lock_exclusive().is_err() { + eprintln!("Waiting for lock on Nargo.toml..."); + } + + file.lock_exclusive().expect("Failed to lock Nargo.toml"); + } else { + if file.try_lock_shared().is_err() { + eprintln!("Waiting for lock on Nargo.toml..."); + } + + file.lock_shared().expect("Failed to lock Nargo.toml"); + } + Some(file) + } + None => None, + }; + + match command { + NargoCommand::New(args) => new_cmd::run(args, config), + NargoCommand::Init(args) => init_cmd::run(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), + NargoCommand::GenerateCompletionScript(args) => generate_completion_script_cmd::run(args), + }?; + + if let Some(lock_file) = lock_file { + lock_file.unlock().expect("Failed to unlock Nargo.toml"); + } + + Ok(()) +} + +#[cfg(feature = "codegen-docs")] +pub(crate) fn start_cli() -> eyre::Result<()> { + let markdown: String = clap_markdown::help_markdown::(); + println!("{markdown}"); + Ok(()) +} + +/// Some commands have package options, which we use here to decide whether to +/// alter `--program-dir` to point at a manifest, depending on whether we want +/// to work on a specific package or the entire workspace. +fn command_scope(cmd: &NargoCommand) -> CommandScope { + match &cmd { + NargoCommand::Check(cmd) => cmd.package_options.scope(), + NargoCommand::Compile(cmd) => cmd.package_options.scope(), + NargoCommand::Execute(cmd) => cmd.package_options.scope(), + NargoCommand::Export(cmd) => cmd.package_options.scope(), + NargoCommand::Test(cmd) => cmd.package_options.scope(), + NargoCommand::Info(cmd) => cmd.package_options.scope(), + NargoCommand::Fmt(cmd) => cmd.package_options.scope(), + NargoCommand::Debug(cmd) => { + if cmd.package.is_some() { + CommandScope::Workspace + } else { + CommandScope::CurrentPackage + } + } + NargoCommand::New(..) + | NargoCommand::Init(..) + | NargoCommand::Lsp(..) + | NargoCommand::Dap(..) + | NargoCommand::GenerateCompletionScript(..) => CommandScope::Any, + } +} + +/// A manifest directory we need to change into, if the command needs it. +fn command_dir(cmd: &NargoCommand, program_dir: &Path) -> Result, ManifestError> { + let workspace = match command_scope(cmd) { + CommandScope::Workspace => true, + CommandScope::CurrentPackage => false, + CommandScope::Any => return Ok(None), + }; + Ok(Some(nargo_toml::find_root(program_dir, workspace)?)) +} + +fn needs_lock(cmd: &NargoCommand) -> Option { + match cmd { + NargoCommand::Check(..) + | NargoCommand::Compile(..) + | NargoCommand::Execute(..) + | NargoCommand::Export(..) + | NargoCommand::Info(..) => Some(true), + NargoCommand::Debug(..) | NargoCommand::Test(..) => Some(false), + NargoCommand::Fmt(..) + | NargoCommand::New(..) + | NargoCommand::Init(..) + | NargoCommand::Lsp(..) + | NargoCommand::Dap(..) + | NargoCommand::GenerateCompletionScript(..) => None, + } +} + +#[cfg(test)] +mod tests { + use clap::Parser; + #[test] + fn test_parse_invalid_expression_width() { + let cmd = "nargo --program-dir . compile --expression-width 1"; + let res = super::NargoCli::try_parse_from(cmd.split_ascii_whitespace()); + + let err = res.expect_err("should fail because of invalid width"); + assert!(err.to_string().contains("expression-width")); + assert!(err + .to_string() + .contains(acvm::compiler::MIN_EXPRESSION_WIDTH.to_string().as_str())); + } +} diff --git a/tooling/nargo_cli/src/cli/new_cmd.rs b/tooling/nargo_cli/src/cli/new_cmd.rs new file mode 100644 index 00000000000..db9257b8aa0 --- /dev/null +++ b/tooling/nargo_cli/src/cli/new_cmd.rs @@ -0,0 +1,54 @@ +use crate::errors::CliError; + +use super::{init_cmd::initialize_project, NargoConfig}; +use clap::Args; +use nargo::package::{CrateName, PackageType}; +use std::path::PathBuf; + +/// Create a Noir project in a new directory. +#[derive(Debug, Clone, Args)] +pub(crate) struct NewCommand { + /// The path to save the new project + path: PathBuf, + + /// Name of the package [default: package directory name] + #[clap(long)] + name: Option, + + /// Use a library template + #[arg(long, conflicts_with = "bin", conflicts_with = "contract")] + pub(crate) lib: bool, + + /// Use a binary template [default] + #[arg(long, conflicts_with = "lib", conflicts_with = "contract")] + pub(crate) bin: bool, + + /// Use a contract template + #[arg(long, conflicts_with = "lib", conflicts_with = "bin")] + pub(crate) contract: bool, +} + +pub(crate) fn run(args: NewCommand, config: NargoConfig) -> Result<(), CliError> { + let package_dir = config.program_dir.join(&args.path); + + if package_dir.exists() { + return Err(CliError::DestinationAlreadyExists(package_dir)); + } + + let package_name = match args.name { + Some(name) => name, + None => { + let name = args.path.file_name().unwrap().to_str().unwrap(); + name.parse().map_err(|_| CliError::InvalidPackageName(name.into()))? + } + }; + let package_type = if args.lib { + PackageType::Library + } else if args.contract { + PackageType::Contract + } else { + PackageType::Binary + }; + initialize_project(package_dir, package_name, package_type); + Ok(()) +} diff --git a/tooling/nargo_cli/src/cli/noir_template_files/binary.nr b/tooling/nargo_cli/src/cli/noir_template_files/binary.nr new file mode 100644 index 00000000000..3c30bf08424 --- /dev/null +++ b/tooling/nargo_cli/src/cli/noir_template_files/binary.nr @@ -0,0 +1,11 @@ +fn main(x: Field, y: pub Field) { + assert(x != y); +} + +#[test] +fn test_main() { + main(1, 2); + + // Uncomment to make test fail + // main(1, 1); +} diff --git a/tooling/nargo_cli/src/cli/noir_template_files/contract.nr b/tooling/nargo_cli/src/cli/noir_template_files/contract.nr new file mode 100644 index 00000000000..3cd3b5b3766 --- /dev/null +++ b/tooling/nargo_cli/src/cli/noir_template_files/contract.nr @@ -0,0 +1,5 @@ +contract Main { + 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/noir_template_files/library.nr b/tooling/nargo_cli/src/cli/noir_template_files/library.nr new file mode 100644 index 00000000000..b874c958a9b --- /dev/null +++ b/tooling/nargo_cli/src/cli/noir_template_files/library.nr @@ -0,0 +1,11 @@ +fn not_equal(x: Field, y: Field) -> bool { + x != y +} + +#[test] +fn test_not_equal() { + assert(not_equal(1, 2)); + + // Uncomment to make test fail + // assert(not_equal(1, 1)); +} diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs new file mode 100644 index 00000000000..9bf3ae9fedf --- /dev/null +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -0,0 +1,530 @@ +use std::{ + collections::{BTreeMap, HashMap}, + fmt::Display, + panic::{catch_unwind, UnwindSafe}, + path::PathBuf, + sync::{mpsc, Mutex}, + thread, + time::Duration, +}; + +use acvm::{BlackBoxFunctionSolver, FieldElement}; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use clap::Args; +use fm::FileManager; +use formatters::{Formatter, JsonFormatter, PrettyFormatter, TerseFormatter}; +use nargo::{ + foreign_calls::DefaultForeignCallBuilder, insert_all_files_for_workspace_into_file_manager, + ops::TestStatus, package::Package, parse_all, prepare_package, workspace::Workspace, + PrintOutput, +}; +use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; +use noirc_driver::{check_crate, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_frontend::hir::{FunctionNameMatch, ParsedFiles}; + +use crate::{cli::check_cmd::check_crate_and_report_errors, errors::CliError}; + +use super::{NargoConfig, PackageOptions}; + +mod formatters; + +/// 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, + + /// Display output of `println` statements + #[arg(long)] + show_output: bool, + + /// Only run tests that match exactly + #[clap(long)] + exact: bool, + + #[clap(flatten)] + pub(super) package_options: PackageOptions, + + #[clap(flatten)] + compile_options: CompileOptions, + + /// JSON RPC url to solve oracle calls + #[clap(long)] + oracle_resolver: Option, + + /// Number of threads used for running tests in parallel + #[clap(long, default_value_t = rayon::current_num_threads())] + test_threads: usize, + + /// Configure formatting of output + #[clap(long)] + format: Option, + + /// Display one character per test instead of one line + #[clap(short = 'q', long = "quiet")] + quiet: bool, +} + +#[derive(Debug, Copy, Clone, clap::ValueEnum)] +enum Format { + /// Print verbose output + Pretty, + /// Display one character per test + Terse, + /// Output a JSON Lines document + Json, +} + +impl Format { + fn formatter(&self) -> Box { + match self { + Format::Pretty => Box::new(PrettyFormatter), + Format::Terse => Box::new(TerseFormatter), + Format::Json => Box::new(JsonFormatter), + } + } +} + +impl Display for Format { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Format::Pretty => write!(f, "pretty"), + Format::Terse => write!(f, "terse"), + Format::Json => write!(f, "json"), + } + } +} + +struct Test<'a> { + name: String, + package_name: String, + runner: Box (TestStatus, String) + Send + UnwindSafe + 'a>, +} + +struct TestResult { + name: String, + package_name: String, + status: TestStatus, + output: String, + time_to_run: Duration, +} + +const STACK_SIZE: usize = 4 * 1024 * 1024; + +pub(crate) fn run(args: TestCommand, config: NargoConfig) -> Result<(), CliError> { + let toml_path = get_package_manifest(&config.program_dir)?; + let selection = args.package_options.package_selection(); + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; + + let mut file_manager = workspace.new_file_manager(); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut file_manager); + let parsed_files = parse_all(&file_manager); + + let pattern = match &args.test_name { + Some(name) => { + if args.exact { + FunctionNameMatch::Exact(name) + } else { + FunctionNameMatch::Contains(name) + } + } + None => FunctionNameMatch::Anything, + }; + + let formatter: Box = if let Some(format) = args.format { + format.formatter() + } else if args.quiet { + Box::new(TerseFormatter) + } else { + Box::new(PrettyFormatter) + }; + + let runner = TestRunner { + file_manager: &file_manager, + parsed_files: &parsed_files, + workspace, + args: &args, + pattern, + num_threads: args.test_threads, + formatter, + }; + runner.run() +} + +struct TestRunner<'a> { + file_manager: &'a FileManager, + parsed_files: &'a ParsedFiles, + workspace: Workspace, + args: &'a TestCommand, + pattern: FunctionNameMatch<'a>, + num_threads: usize, + formatter: Box, +} + +impl<'a> TestRunner<'a> { + fn run(&self) -> Result<(), CliError> { + // First compile all packages and collect their tests + let packages_tests = self.collect_packages_tests()?; + + // Now gather all tests and how many are per packages + let mut tests = Vec::new(); + let mut test_count_per_package = BTreeMap::new(); + + for (package_name, package_tests) in packages_tests { + test_count_per_package.insert(package_name, package_tests.len()); + tests.extend(package_tests); + } + + // Now run all tests in parallel, but show output for each package sequentially + let tests_count = tests.len(); + let all_passed = self.run_all_tests(tests, &test_count_per_package); + + if tests_count == 0 { + match &self.pattern { + FunctionNameMatch::Exact(pattern) => { + return Err(CliError::Generic(format!( + "Found 0 tests matching input '{pattern}'.", + ))) + } + FunctionNameMatch::Contains(pattern) => { + return Err(CliError::Generic( + format!("Found 0 tests containing '{pattern}'.",), + )) + } + // If we are running all tests in a crate, having none is not an error + FunctionNameMatch::Anything => {} + }; + } + + if all_passed { + Ok(()) + } else { + Err(CliError::Generic(String::new())) + } + } + + /// Runs all tests. Returns `true` if all tests passed, `false` otherwise. + fn run_all_tests( + &self, + tests: Vec>, + test_count_per_package: &BTreeMap, + ) -> bool { + let mut all_passed = true; + + for (package_name, total_test_count) in test_count_per_package { + self.formatter + .package_start_async(package_name, *total_test_count) + .expect("Could not display package start"); + } + + let (sender, receiver) = mpsc::channel(); + let iter = &Mutex::new(tests.into_iter()); + thread::scope(|scope| { + // Start worker threads + for _ in 0..self.num_threads { + // Clone sender so it's dropped once the thread finishes + let thread_sender = sender.clone(); + thread::Builder::new() + // Specify a larger-than-default stack size to prevent overflowing stack in large programs. + // (the default is 2MB) + .stack_size(STACK_SIZE) + .spawn_scoped(scope, move || loop { + // Get next test to process from the iterator. + let Some(test) = iter.lock().unwrap().next() else { + break; + }; + + self.formatter + .test_start_async(&test.name, &test.package_name) + .expect("Could not display test start"); + + let time_before_test = std::time::Instant::now(); + let (status, output) = match catch_unwind(test.runner) { + Ok((status, output)) => (status, output), + Err(err) => ( + TestStatus::Fail { + message: + // It seems `panic!("...")` makes the error be `&str`, so we handle this common case + if let Some(message) = err.downcast_ref::<&str>() { + message.to_string() + } else { + "An unexpected error happened".to_string() + }, + error_diagnostic: None, + }, + String::new(), + ), + }; + let time_to_run = time_before_test.elapsed(); + + let test_result = TestResult { + name: test.name, + package_name: test.package_name, + status, + output, + time_to_run, + }; + + self.formatter + .test_end_async( + &test_result, + self.file_manager, + self.args.show_output, + self.args.compile_options.deny_warnings, + self.args.compile_options.silence_warnings, + ) + .expect("Could not display test start"); + + if thread_sender.send(test_result).is_err() { + break; + } + }) + .unwrap(); + } + + // Also drop main sender so the channel closes + drop(sender); + + // We'll go package by package, but we might get test results from packages ahead of us. + // We'll buffer those here and show them all at once when we get to those packages. + let mut buffer: HashMap> = HashMap::new(); + for (package_name, total_test_count) in test_count_per_package { + let mut test_report = Vec::new(); + + let mut current_test_count = 0; + let total_test_count = *total_test_count; + + self.formatter + .package_start_sync(package_name, total_test_count) + .expect("Could not display package start"); + + // Check if we have buffered test results for this package + if let Some(buffered_tests) = buffer.remove(package_name) { + for test_result in buffered_tests { + self.display_test_result( + &test_result, + current_test_count + 1, + total_test_count, + ) + .expect("Could not display test status"); + test_report.push(test_result); + current_test_count += 1; + } + } + + if current_test_count < total_test_count { + while let Ok(test_result) = receiver.recv() { + if test_result.status.failed() { + all_passed = false; + } + + // This is a test result from a different package: buffer it. + if &test_result.package_name != package_name { + buffer + .entry(test_result.package_name.clone()) + .or_default() + .push(test_result); + continue; + } + + self.display_test_result( + &test_result, + current_test_count + 1, + total_test_count, + ) + .expect("Could not display test status"); + test_report.push(test_result); + current_test_count += 1; + if current_test_count == total_test_count { + break; + } + } + } + + self.formatter + .package_end( + package_name, + &test_report, + self.file_manager, + self.args.show_output, + self.args.compile_options.deny_warnings, + self.args.compile_options.silence_warnings, + ) + .expect("Could not display test report"); + } + }); + + all_passed + } + + /// Compiles all packages in parallel and returns their tests + fn collect_packages_tests(&'a self) -> Result>>, CliError> { + let mut package_tests = BTreeMap::new(); + let mut error = None; + + let (sender, receiver) = mpsc::channel(); + let iter = &Mutex::new(self.workspace.into_iter()); + + thread::scope(|scope| { + // Start worker threads + for _ in 0..self.num_threads { + // Clone sender so it's dropped once the thread finishes + let thread_sender = sender.clone(); + thread::Builder::new() + // Specify a larger-than-default stack size to prevent overflowing stack in large programs. + // (the default is 2MB) + .stack_size(STACK_SIZE) + .spawn_scoped(scope, move || loop { + // Get next package to process from the iterator. + let Some(package) = iter.lock().unwrap().next() else { + break; + }; + let tests = self.collect_package_tests::( + package, + self.args.oracle_resolver.as_deref(), + Some(self.workspace.root_dir.clone()), + package.name.to_string(), + ); + if thread_sender.send((package, tests)).is_err() { + break; + } + }) + .unwrap(); + } + + // Also drop main sender so the channel closes + drop(sender); + + for (package, tests) in receiver.iter() { + match tests { + Ok(tests) => { + package_tests.insert(package.name.to_string(), tests); + } + Err(err) => { + error = Some(err); + } + } + } + }); + + if let Some(error) = error { + Err(error) + } else { + Ok(package_tests) + } + } + + /// Compiles a single package and returns all of its tests + fn collect_package_tests + Default>( + &'a self, + package: &'a Package, + foreign_call_resolver_url: Option<&'a str>, + root_path: Option, + package_name: String, + ) -> Result>, CliError> { + let test_functions = self.get_tests_in_package(package)?; + + let tests: Vec = test_functions + .into_iter() + .map(|test_name| { + let test_name_copy = test_name.clone(); + let root_path = root_path.clone(); + let package_name_clone = package_name.clone(); + let package_name_clone2 = package_name.clone(); + let runner = Box::new(move || { + self.run_test::( + package, + &test_name, + foreign_call_resolver_url, + root_path, + package_name_clone.clone(), + ) + }); + Test { name: test_name_copy, package_name: package_name_clone2, runner } + }) + .collect(); + + Ok(tests) + } + + /// Compiles a single package and returns all of its test names + fn get_tests_in_package(&'a self, package: &'a Package) -> Result, CliError> { + let (mut context, crate_id) = + prepare_package(self.file_manager, self.parsed_files, package); + check_crate_and_report_errors(&mut context, crate_id, &self.args.compile_options)?; + + Ok(context + .get_all_test_functions_in_crate_matching(&crate_id, self.pattern) + .into_iter() + .map(|(test_name, _)| test_name) + .collect()) + } + + /// Runs a single test and returns its status together with whatever was printed to stdout + /// during the test. + fn run_test + Default>( + &'a self, + package: &Package, + fn_name: &str, + foreign_call_resolver_url: Option<&str>, + root_path: Option, + package_name: String, + ) -> (TestStatus, String) { + // 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(self.file_manager, self.parsed_files, package); + check_crate(&mut context, crate_id, &self.args.compile_options) + .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(); + let mut output_string = String::new(); + + let test_status = nargo::ops::run_test( + &blackbox_solver, + &mut context, + test_function, + PrintOutput::String(&mut output_string), + &self.args.compile_options, + |output, base| { + DefaultForeignCallBuilder { + output, + enable_mocks: true, + resolver_url: foreign_call_resolver_url.map(|s| s.to_string()), + root_path: root_path.clone(), + package_name: Some(package_name.clone()), + } + .build_with_base(base) + }, + ); + (test_status, output_string) + } + + /// Display the status of a single test + fn display_test_result( + &'a self, + test_result: &'a TestResult, + current_test_count: usize, + total_test_count: usize, + ) -> std::io::Result<()> { + self.formatter.test_end_sync( + test_result, + current_test_count, + total_test_count, + self.file_manager, + self.args.show_output, + self.args.compile_options.deny_warnings, + self.args.compile_options.silence_warnings, + ) + } +} diff --git a/tooling/nargo_cli/src/cli/test_cmd/formatters.rs b/tooling/nargo_cli/src/cli/test_cmd/formatters.rs new file mode 100644 index 00000000000..75cf14ba120 --- /dev/null +++ b/tooling/nargo_cli/src/cli/test_cmd/formatters.rs @@ -0,0 +1,540 @@ +use std::{io::Write, panic::RefUnwindSafe, time::Duration}; + +use fm::FileManager; +use nargo::ops::TestStatus; +use noirc_errors::{reporter::stack_trace, FileDiagnostic}; +use serde_json::{json, Map}; +use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, StandardStreamLock, WriteColor}; + +use super::TestResult; + +/// A formatter for showing test results. +/// +/// The order of events is: +/// 1. Compilation of all packages happen (in parallel). There's no formatter method for this. +/// 2. If compilation is successful, one `package_start_async` for each package. +/// 3. For each test, one `test_start_async` event +/// (there's no `test_start_sync` event because it would happen right before `test_end_sync`) +/// 4. For each package, sequentially: +/// a. A `package_start_sync` event +/// b. One `test_end` event for each test +/// a. A `package_end` event +/// +/// The reason we have some `sync` and `async` events is that formatters that show output +/// to humans rely on the `sync` events to show a more predictable output (package by package), +/// and formatters that output to a machine-readable format (like JSON) rely on the `async` +/// events to show things as soon as they happen, regardless of a package ordering. +pub(super) trait Formatter: Send + Sync + RefUnwindSafe { + fn package_start_async(&self, package_name: &str, test_count: usize) -> std::io::Result<()>; + + fn package_start_sync(&self, package_name: &str, test_count: usize) -> std::io::Result<()>; + + fn test_start_async(&self, name: &str, package_name: &str) -> std::io::Result<()>; + + #[allow(clippy::too_many_arguments)] + fn test_end_async( + &self, + test_result: &TestResult, + file_manager: &FileManager, + show_output: bool, + deny_warnings: bool, + silence_warnings: bool, + ) -> std::io::Result<()>; + + #[allow(clippy::too_many_arguments)] + fn test_end_sync( + &self, + test_result: &TestResult, + current_test_count: usize, + total_test_count: usize, + file_manager: &FileManager, + show_output: bool, + deny_warnings: bool, + silence_warnings: bool, + ) -> std::io::Result<()>; + + fn package_end( + &self, + package_name: &str, + test_results: &[TestResult], + file_manager: &FileManager, + show_output: bool, + deny_warnings: bool, + silence_warnings: bool, + ) -> std::io::Result<()>; +} + +pub(super) struct PrettyFormatter; + +impl Formatter for PrettyFormatter { + fn package_start_async(&self, _package_name: &str, _test_count: usize) -> std::io::Result<()> { + Ok(()) + } + + fn package_start_sync(&self, package_name: &str, test_count: usize) -> std::io::Result<()> { + package_start(package_name, test_count) + } + + fn test_start_async(&self, _name: &str, _package_name: &str) -> std::io::Result<()> { + Ok(()) + } + + fn test_end_async( + &self, + _test_result: &TestResult, + _file_manager: &FileManager, + _show_output: bool, + _deny_warnings: bool, + _silence_warnings: bool, + ) -> std::io::Result<()> { + Ok(()) + } + + fn test_end_sync( + &self, + test_result: &TestResult, + _current_test_count: usize, + _total_test_count: usize, + file_manager: &FileManager, + show_output: bool, + deny_warnings: bool, + silence_warnings: bool, + ) -> std::io::Result<()> { + let writer = StandardStream::stderr(ColorChoice::Always); + let mut writer = writer.lock(); + + let is_slow = test_result.time_to_run >= Duration::from_secs(30); + let show_time = |writer: &mut StandardStreamLock<'_>| { + if is_slow { + write!(writer, " <{:.3}s>", test_result.time_to_run.as_secs_f64()) + } else { + Ok(()) + } + }; + + write!(writer, "[{}] Testing {}... ", &test_result.package_name, &test_result.name)?; + writer.flush()?; + + match &test_result.status { + TestStatus::Pass { .. } => { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?; + write!(writer, "ok")?; + writer.reset()?; + show_time(&mut writer)?; + writeln!(writer)?; + } + TestStatus::Fail { message, error_diagnostic } => { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?; + write!(writer, "FAIL\n{message}\n")?; + writer.reset()?; + show_time(&mut writer)?; + writeln!(writer)?; + if let Some(diag) = error_diagnostic { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[diag.clone()], + deny_warnings, + silence_warnings, + ); + } + } + TestStatus::Skipped { .. } => { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?; + write!(writer, "skipped")?; + writer.reset()?; + show_time(&mut writer)?; + writeln!(writer)?; + } + TestStatus::CompileError(file_diagnostic) => { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[file_diagnostic.clone()], + deny_warnings, + silence_warnings, + ); + } + } + + if show_output && !test_result.output.is_empty() { + writeln!(writer, "--- {} stdout ---", test_result.name)?; + write!(writer, "{}", test_result.output)?; + let name_len = test_result.name.len(); + writeln!(writer, "{}", "-".repeat(name_len + "--- stdout ---".len())) + } else { + Ok(()) + } + } + + fn package_end( + &self, + package_name: &str, + test_results: &[TestResult], + _file_manager: &FileManager, + _show_output: bool, + _deny_warnings: bool, + _silence_warnings: bool, + ) -> std::io::Result<()> { + let writer = StandardStream::stderr(ColorChoice::Always); + let mut writer = writer.lock(); + + let failed_tests: Vec<_> = test_results + .iter() + .filter_map(|test_result| test_result.status.failed().then_some(&test_result.name)) + .collect(); + + if !failed_tests.is_empty() { + writeln!(writer)?; + writeln!(writer, "[{}] Failures:", package_name)?; + for failed_test in failed_tests { + writeln!(writer, " {}", failed_test)?; + } + writeln!(writer)?; + } + + write!(writer, "[{}] ", package_name)?; + + let count_all = test_results.len(); + let count_failed = + test_results.iter().filter(|test_result| test_result.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)))?; + write!(writer, "{count_all} test{plural} passed")?; + writer.reset()?; + writeln!(writer)?; + } else { + let count_passed = count_all - count_failed; + let plural_failed = if count_failed == 1 { "" } else { "s" }; + let plural_passed = if count_passed == 1 { "" } else { "s" }; + + if count_passed != 0 { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?; + write!(writer, "{count_passed} test{plural_passed} passed, ")?; + } + + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?; + writeln!(writer, "{count_failed} test{plural_failed} failed")?; + writer.reset()?; + } + + Ok(()) + } +} + +pub(super) struct TerseFormatter; + +impl Formatter for TerseFormatter { + fn package_start_async(&self, _package_name: &str, _test_count: usize) -> std::io::Result<()> { + Ok(()) + } + + fn package_start_sync(&self, package_name: &str, test_count: usize) -> std::io::Result<()> { + package_start(package_name, test_count) + } + + fn test_start_async(&self, _name: &str, _package_name: &str) -> std::io::Result<()> { + Ok(()) + } + + fn test_end_async( + &self, + _test_result: &TestResult, + _file_manager: &FileManager, + _show_output: bool, + _deny_warnings: bool, + _silence_warnings: bool, + ) -> std::io::Result<()> { + Ok(()) + } + + fn test_end_sync( + &self, + test_result: &TestResult, + current_test_count: usize, + total_test_count: usize, + _file_manager: &FileManager, + _show_output: bool, + _deny_warnings: bool, + _silence_warnings: bool, + ) -> std::io::Result<()> { + let writer = StandardStream::stderr(ColorChoice::Always); + let mut writer = writer.lock(); + + match &test_result.status { + TestStatus::Pass => { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?; + write!(writer, ".")?; + writer.reset()?; + } + TestStatus::Fail { .. } | TestStatus::CompileError(_) => { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?; + write!(writer, "F")?; + writer.reset()?; + } + TestStatus::Skipped => { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?; + write!(writer, "s")?; + writer.reset()?; + } + } + + // How many tests ('.', 'F', etc.) to print per line. + // We use 88 which is a bit more than the traditional 80 columns (screens are larger these days) + // but we also want the output to be readable in case the terminal isn't maximized. + const MAX_TESTS_PER_LINE: usize = 88; + + if current_test_count % MAX_TESTS_PER_LINE == 0 && current_test_count < total_test_count { + writeln!(writer, " {}/{}", current_test_count, total_test_count)?; + } + + Ok(()) + } + + fn package_end( + &self, + package_name: &str, + test_results: &[TestResult], + file_manager: &FileManager, + show_output: bool, + deny_warnings: bool, + silence_warnings: bool, + ) -> std::io::Result<()> { + let writer = StandardStream::stderr(ColorChoice::Always); + let mut writer = writer.lock(); + + if !test_results.is_empty() { + writeln!(writer)?; + } + + for test_result in test_results { + if (show_output && !test_result.output.is_empty()) || test_result.status.failed() { + writeln!(writer, "--- {} stdout ---", test_result.name)?; + if !test_result.output.is_empty() { + write!(writer, "{}", test_result.output)?; + } + + match &test_result.status { + TestStatus::Pass | TestStatus::Skipped => (), + TestStatus::Fail { message, error_diagnostic } => { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?; + writeln!(writer, "{message}")?; + writer.reset()?; + if let Some(diag) = error_diagnostic { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[diag.clone()], + deny_warnings, + silence_warnings, + ); + } + } + TestStatus::CompileError(file_diagnostic) => { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[file_diagnostic.clone()], + deny_warnings, + silence_warnings, + ); + } + } + + let name_len = test_result.name.len(); + writeln!(writer, "{}", "-".repeat(name_len + "--- stdout ---".len()))?; + } + } + + let failed_tests: Vec<_> = test_results + .iter() + .filter_map(|test_result| test_result.status.failed().then_some(&test_result.name)) + .collect(); + + if !failed_tests.is_empty() { + writeln!(writer)?; + writeln!(writer, "[{}] Failures:", package_name)?; + for failed_test in failed_tests { + writeln!(writer, " {}", failed_test)?; + } + writeln!(writer)?; + } + + write!(writer, "[{}] ", package_name)?; + + let count_all = test_results.len(); + let count_failed = + test_results.iter().filter(|test_result| test_result.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)))?; + write!(writer, "{count_all} test{plural} passed")?; + writer.reset()?; + writeln!(writer)?; + } else { + let count_passed = count_all - count_failed; + let plural_failed = if count_failed == 1 { "" } else { "s" }; + let plural_passed = if count_passed == 1 { "" } else { "s" }; + + if count_passed != 0 { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?; + write!(writer, "{count_passed} test{plural_passed} passed, ")?; + } + + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?; + writeln!(writer, "{count_failed} test{plural_failed} failed")?; + writer.reset()?; + } + + Ok(()) + } +} + +pub(super) struct JsonFormatter; + +impl Formatter for JsonFormatter { + fn package_start_async(&self, package_name: &str, test_count: usize) -> std::io::Result<()> { + let json = json!({"type": "suite", "event": "started", "name": package_name, "test_count": test_count}); + println!("{json}"); + Ok(()) + } + + fn package_start_sync(&self, _package_name: &str, _test_count: usize) -> std::io::Result<()> { + Ok(()) + } + + fn test_start_async(&self, name: &str, package_name: &str) -> std::io::Result<()> { + let json = json!({"type": "test", "event": "started", "name": name, "suite": package_name}); + println!("{json}"); + Ok(()) + } + + fn test_end_async( + &self, + test_result: &TestResult, + file_manager: &FileManager, + show_output: bool, + _deny_warnings: bool, + silence_warnings: bool, + ) -> std::io::Result<()> { + let mut json = Map::new(); + json.insert("type".to_string(), json!("test")); + json.insert("name".to_string(), json!(&test_result.name)); + json.insert("suite".to_string(), json!(&test_result.package_name)); + json.insert("exec_time".to_string(), json!(test_result.time_to_run.as_secs_f64())); + + let mut stdout = String::new(); + if show_output && !test_result.output.is_empty() { + stdout.push_str(test_result.output.trim()); + } + + match &test_result.status { + TestStatus::Pass => { + json.insert("event".to_string(), json!("ok")); + } + TestStatus::Fail { message, error_diagnostic } => { + json.insert("event".to_string(), json!("failed")); + + if !stdout.is_empty() { + stdout.push('\n'); + } + stdout.push_str(message.trim()); + + if let Some(diagnostic) = error_diagnostic { + if !(diagnostic.diagnostic.is_warning() && silence_warnings) { + stdout.push('\n'); + stdout.push_str(&diagnostic_to_string(diagnostic, file_manager)); + } + } + } + TestStatus::Skipped => { + json.insert("event".to_string(), json!("ignored")); + } + TestStatus::CompileError(diagnostic) => { + json.insert("event".to_string(), json!("failed")); + + if !(diagnostic.diagnostic.is_warning() && silence_warnings) { + if !stdout.is_empty() { + stdout.push('\n'); + } + stdout.push_str(&diagnostic_to_string(diagnostic, file_manager)); + } + } + } + + if !stdout.is_empty() { + json.insert("stdout".to_string(), json!(stdout)); + } + + let json = json!(json); + println!("{json}"); + + Ok(()) + } + + fn test_end_sync( + &self, + _test_result: &TestResult, + _current_test_count: usize, + _total_test_count: usize, + _file_manager: &FileManager, + _show_output: bool, + _deny_warnings: bool, + _silence_warnings: bool, + ) -> std::io::Result<()> { + Ok(()) + } + + fn package_end( + &self, + _package_name: &str, + test_results: &[TestResult], + _file_manager: &FileManager, + _show_output: bool, + _deny_warnings: bool, + _silence_warnings: bool, + ) -> std::io::Result<()> { + let mut passed = 0; + let mut failed = 0; + let mut ignored = 0; + for test_result in test_results { + match &test_result.status { + TestStatus::Pass => passed += 1, + TestStatus::Fail { .. } | TestStatus::CompileError(..) => failed += 1, + TestStatus::Skipped => ignored += 1, + } + } + let event = if failed == 0 { "ok" } else { "failed" }; + let json = json!({"type": "suite", "event": event, "passed": passed, "failed": failed, "ignored": ignored}); + println!("{json}"); + Ok(()) + } +} + +fn package_start(package_name: &str, test_count: usize) -> std::io::Result<()> { + let plural = if test_count == 1 { "" } else { "s" }; + println!("[{package_name}] Running {test_count} test function{plural}"); + Ok(()) +} + +fn diagnostic_to_string(file_diagnostic: &FileDiagnostic, file_manager: &FileManager) -> String { + let file_map = file_manager.as_file_map(); + + let custom_diagnostic = &file_diagnostic.diagnostic; + let mut message = String::new(); + message.push_str(custom_diagnostic.message.trim()); + + for note in &custom_diagnostic.notes { + message.push('\n'); + message.push_str(note.trim()); + } + + if let Ok(name) = file_map.get_name(file_diagnostic.file_id) { + message.push('\n'); + message.push_str(&format!("at {name}")); + } + + if !custom_diagnostic.call_stack.is_empty() { + message.push('\n'); + message.push_str(&stack_trace(file_map, &custom_diagnostic.call_stack)); + } + + message +} diff --git a/tooling/nargo_cli/src/errors.rs b/tooling/nargo_cli/src/errors.rs new file mode 100644 index 00000000000..9255d6fc6a6 --- /dev/null +++ b/tooling/nargo_cli/src/errors.rs @@ -0,0 +1,77 @@ +use acvm::{acir::native_types::WitnessStackError, FieldElement}; +use nargo::{errors::CompileError, NargoError}; +use nargo_toml::ManifestError; +use noir_debugger::errors::DapError; +use noirc_abi::{ + errors::{AbiError, InputParserError}, + input_parser::InputValue, + AbiReturnType, +}; +use std::path::PathBuf; +use thiserror::Error; + +#[derive(Debug, 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: cannot find {0}.toml file.\n Expected location: {1:?} \n Please generate this file at the expected location." + )] + MissingTomlFile(String, PathBuf), + + /// Input parsing error + #[error(transparent)] + InputParserError(#[from] InputParserError), + + /// WitnessStack serialization error + #[error(transparent)] + WitnessStackSerialization(#[from] WitnessStackError), + + #[error("Error: could not deserialize build program: {0}")] + ProgramSerializationError(String), +} + +#[derive(Debug, Error)] +pub(crate) enum CliError { + #[error("{0}")] + Generic(String), + + #[error("Error: destination {} already exists", .0.display())] + DestinationAlreadyExists(PathBuf), + + #[error("Invalid package name {0}. Did you mean to use `--name`?")] + InvalidPackageName(String), + + /// ABI encoding/decoding error + #[error(transparent)] + AbiError(#[from] AbiError), + + /// Filesystem errors + #[error(transparent)] + FilesystemError(#[from] FilesystemError), + + #[error(transparent)] + LspError(#[from] async_lsp::Error), + + #[error(transparent)] + DapError(#[from] DapError), + + /// Error from Nargo + #[error(transparent)] + NargoError(#[from] NargoError), + + /// Error from Manifest + #[error(transparent)] + ManifestError(#[from] ManifestError), + + /// Error from the compilation pipeline + #[error(transparent)] + CompileError(#[from] CompileError), + + #[error("Unexpected return value: expected {expected:?}; got {actual:?}")] + UnexpectedReturn { expected: InputValue, actual: Option }, + + #[error("Missing return witnesses; expected {expected:?}")] + MissingReturn { expected: AbiReturnType }, +} diff --git a/tooling/nargo_cli/src/main.rs b/tooling/nargo_cli/src/main.rs new file mode 100644 index 00000000000..3ea167b7ffa --- /dev/null +++ b/tooling/nargo_cli/src/main.rs @@ -0,0 +1,47 @@ +#![forbid(unsafe_code)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + +//! Nargo is the package manager for Noir +//! This name was used because it sounds like `cargo` and +//! Noir Package Manager abbreviated is npm, which is already taken. + +mod cli; +mod errors; + +use std::env; + +use color_eyre::config::HookBuilder; + +use tracing_appender::rolling; +use tracing_subscriber::{fmt::format::FmtSpan, EnvFilter}; + +const PANIC_MESSAGE: &str = "This is a bug. We may have already fixed this in newer versions of Nargo so try searching for similar issues at https://github.com/noir-lang/noir/issues/.\nIf there isn't an open issue for this bug, consider opening one at https://github.com/noir-lang/noir/issues/new?labels=bug&template=bug_report.yml"; + +fn main() { + setup_tracing(); + + // Register a panic hook to display more readable panic messages to end-users + let (panic_hook, _) = + HookBuilder::default().display_env_section(false).panic_section(PANIC_MESSAGE).into_hooks(); + panic_hook.install(); + + if let Err(report) = cli::start_cli() { + eprintln!("{report}"); + std::process::exit(1); + } +} + +fn setup_tracing() { + let subscriber = tracing_subscriber::fmt() + .with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE) + .with_env_filter(EnvFilter::from_env("NOIR_LOG")); + + if let Ok(log_dir) = env::var("NARGO_LOG_DIR") { + let debug_file = rolling::daily(log_dir, "nargo-log"); + subscriber.with_writer(debug_file).with_ansi(false).json().init(); + } else { + subscriber.with_ansi(true).init(); + } +} diff --git a/tooling/nargo_cli/tests/execute.rs b/tooling/nargo_cli/tests/execute.rs new file mode 100644 index 00000000000..77d77cfd902 --- /dev/null +++ b/tooling/nargo_cli/tests/execute.rs @@ -0,0 +1,23 @@ +#[allow(unused_imports)] +#[cfg(test)] +mod tests { + // Some of these imports are consumed by the injected tests + use assert_cmd::prelude::*; + use predicates::prelude::*; + + use std::collections::BTreeMap; + use std::fs; + use std::path::PathBuf; + use std::process::Command; + + use super::*; + + // Utilities to keep the test matrix labels more intuitive. + #[derive(Debug, Clone, Copy)] + struct ForceBrillig(pub bool); + #[derive(Debug, Clone, Copy)] + struct Inliner(pub i64); + + // include tests generated by `build.rs` + include!(concat!(env!("OUT_DIR"), "/execute.rs")); +} diff --git a/tooling/nargo_cli/tests/hello_world.rs b/tooling/nargo_cli/tests/hello_world.rs new file mode 100644 index 00000000000..6b6931542b5 --- /dev/null +++ b/tooling/nargo_cli/tests/hello_world.rs @@ -0,0 +1,44 @@ +//! This integration test aims to mirror the steps taken by a new user using Nargo for the first time. +//! It then follows the steps published at https://noir-lang.org/docs/getting_started/create_a_project +//! Any modifications to the commands run here MUST be documented in the noir-lang book. + +use assert_cmd::prelude::*; +use predicates::prelude::*; +use std::process::Command; + +use assert_fs::prelude::{FileWriteStr, PathAssert, PathChild}; + +#[test] +fn hello_world_example() { + let test_dir = assert_fs::TempDir::new().unwrap(); + std::env::set_current_dir(&test_dir).unwrap(); + + let project_name = "hello_world"; + let project_dir = test_dir.child(project_name); + + // `nargo new hello_world` + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("new").arg(project_name); + cmd.assert().success().stdout(predicate::str::contains("Project successfully created!")); + + project_dir.child("src").assert(predicate::path::is_dir()); + project_dir.child("Nargo.toml").assert(predicate::path::is_file()); + + std::env::set_current_dir(&project_dir).unwrap(); + + // `nargo check` + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("check"); + cmd.assert() + .success() + .stdout(predicate::str::contains("Constraint system successfully built!")); + + project_dir.child("Prover.toml").assert(predicate::path::is_file()); + + // `nargo execute` + project_dir.child("Prover.toml").write_str("x = 1\ny = 2").unwrap(); + + let mut cmd = Command::cargo_bin("nargo").unwrap(); + cmd.arg("execute"); + cmd.assert().success(); +} diff --git a/tooling/nargo_cli/tests/stdlib-props.proptest-regressions b/tooling/nargo_cli/tests/stdlib-props.proptest-regressions new file mode 100644 index 00000000000..d41d504e530 --- /dev/null +++ b/tooling/nargo_cli/tests/stdlib-props.proptest-regressions @@ -0,0 +1,8 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 88db0227d5547742f771c14b1679f6783570b46bf7cf9e6897ee1aca4bd5034d # shrinks to io = SnippetInputOutput { description: "force_brillig = false, max_len = 200", inputs: {"input": Vec([Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(1), Field(5), Field(20), Field(133), Field(233), Field(99), Field(2⁶), Field(196), Field(232), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0)]), "message_size": Field(2⁶)}, expected_output: Vec([Field(102), Field(26), Field(94), Field(212), Field(102), Field(1), Field(215), Field(217), Field(167), Field(175), Field(158), Field(18), Field(20), Field(244), Field(158), Field(200), Field(2⁷), Field(186), Field(251), Field(243), Field(20), Field(207), Field(22), Field(3), Field(139), Field(81), Field(207), Field(2⁴), Field(50), Field(167), Field(1), Field(163)]) } +cc 0f334fe0c29748e8d0964d63f0d1f3a4eee536afa665eabc838045d8e1c67792 # shrinks to io = SnippetInputOutput { description: "force_brillig = true, max_len = 135", inputs: {"input": Vec([Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(0), Field(29), Field(131), Field(217), Field(115), Field(221), Field(92), Field(23), Field(14), Field(58), Field(90), Field(232), Field(155), Field(59), Field(209), Field(2⁴×15), Field(137), Field(214), Field(129), Field(11), Field(140), Field(99), Field(131), Field(188), Field(159), Field(27), Field(206), Field(89), Field(137), Field(248), Field(30), Field(149), Field(194), Field(121), Field(127), Field(245), Field(202), Field(155), Field(203), Field(122), Field(2⁵), Field(209), Field(194), Field(214), Field(11), Field(82), Field(26), Field(244), Field(34), Field(30), Field(125), Field(83), Field(2⁴×13), Field(30), Field(2⁴×10), Field(85), Field(245), Field(220), Field(211), Field(190), Field(46), Field(159), Field(87), Field(74), Field(51), Field(42), Field(202), Field(230), Field(137), Field(127), Field(29), Field(126), Field(243), Field(106), Field(156), Field(2⁴×6), Field(154), Field(70), Field(100), Field(130)]), "message_size": Field(135)}, expected_output: Vec([Field(149), Field(114), Field(68), Field(219), Field(215), Field(147), Field(139), Field(34), Field(145), Field(204), Field(248), Field(145), Field(21), Field(119), Field(2⁵), Field(125), Field(181), Field(142), Field(106), Field(169), Field(202), Field(111), Field(110), Field(6), Field(210), Field(250), Field(2⁴), Field(110), Field(209), Field(2), Field(33), Field(104)]) } diff --git a/tooling/nargo_cli/tests/stdlib-props.rs b/tooling/nargo_cli/tests/stdlib-props.rs new file mode 100644 index 00000000000..780b34bf0c3 --- /dev/null +++ b/tooling/nargo_cli/tests/stdlib-props.rs @@ -0,0 +1,347 @@ +use std::{cell::RefCell, collections::BTreeMap, path::Path}; + +use acvm::{acir::native_types::WitnessStack, AcirField, FieldElement}; +use iter_extended::vecmap; +use nargo::{foreign_calls::DefaultForeignCallBuilder, ops::execute_program, parse_all}; +use noirc_abi::input_parser::InputValue; +use noirc_driver::{ + compile_main, file_manager_with_stdlib, prepare_crate, CompilationResult, CompileOptions, + CompiledProgram, CrateId, +}; +use noirc_frontend::hir::Context; +use proptest::prelude::*; +use sha3::Digest; + +/// Inputs and expected output of a snippet encoded in ABI format. +#[derive(Debug)] +struct SnippetInputOutput { + description: String, + inputs: BTreeMap, + expected_output: InputValue, +} +impl SnippetInputOutput { + fn new(inputs: Vec<(&str, InputValue)>, output: InputValue) -> Self { + Self { + description: "".to_string(), + inputs: inputs.into_iter().map(|(k, v)| (k.to_string(), v)).collect(), + expected_output: output, + } + } + + /// Attach some description to hint at the scenario we are testing. + fn with_description(mut self, description: String) -> Self { + self.description = description; + self + } +} + +/// Prepare a code snippet. +fn prepare_snippet(source: String) -> (Context<'static, 'static>, CrateId) { + let root = Path::new(""); + let file_name = Path::new("main.nr"); + let mut file_manager = file_manager_with_stdlib(root); + file_manager.add_file_with_source(file_name, source).expect( + "Adding source buffer to file manager should never fail when file manager is empty", + ); + let parsed_files = parse_all(&file_manager); + + let mut context = Context::new(file_manager, parsed_files); + let root_crate_id = prepare_crate(&mut context, file_name); + + (context, root_crate_id) +} + +/// Compile the main function in a code snippet. +/// +/// Use `force_brillig` to test it as an unconstrained function without having to change the code. +/// This is useful for methods that use the `runtime::is_unconstrained()` method to change their behavior. +fn prepare_and_compile_snippet( + source: String, + force_brillig: bool, +) -> CompilationResult { + let (mut context, root_crate_id) = prepare_snippet(source); + let options = CompileOptions { force_brillig, ..Default::default() }; + // TODO: Run nargo::ops::transform_program? + compile_main(&mut context, root_crate_id, &options, None) +} + +/// Compile a snippet and run property tests against it by generating random input/output pairs +/// according to the strategy, executing the snippet with the input, and asserting that the +/// output it returns is the one we expect. +fn run_snippet_proptest( + source: String, + force_brillig: bool, + strategy: BoxedStrategy, +) { + let program = match prepare_and_compile_snippet(source.clone(), force_brillig) { + Ok((program, _)) => program, + Err(e) => panic!("failed to compile program; brillig = {force_brillig}:\n{source}\n{e:?}"), + }; + + let pedandic_solving = true; + let blackbox_solver = bn254_blackbox_solver::Bn254BlackBoxSolver(pedandic_solving); + let foreign_call_executor = RefCell::new(DefaultForeignCallBuilder::default().build()); + + // Generate multiple input/output + proptest!(ProptestConfig::with_cases(100), |(io in strategy)| { + let initial_witness = program.abi.encode(&io.inputs, None).expect("failed to encode"); + let mut foreign_call_executor = foreign_call_executor.borrow_mut(); + + let witness_stack: WitnessStack = execute_program( + &program.program, + initial_witness, + &blackbox_solver, + &mut *foreign_call_executor, + ) + .expect("failed to execute"); + + let main_witness = witness_stack.peek().expect("should have return value on witness stack"); + let main_witness = &main_witness.witness; + + let (_, return_value) = program.abi.decode(main_witness).expect("failed to decode"); + let return_value = return_value.expect("should decode a return value"); + + prop_assert_eq!(return_value, io.expected_output, "{}", io.description); + }); +} + +/// Run property tests on a code snippet which is assumed to execute a hashing function with the following signature: +/// +/// ```ignore +/// fn main(input: [u8; {max_len}], message_size: u32) -> pub [u8; 32] +/// ``` +/// +/// The calls are executed with and without forcing brillig, because it seems common for hash functions to run different +/// code paths based on `runtime::is_unconstrained()`. +fn run_hash_proptest( + // Different generic maximum input sizes to try. + max_lengths: &[usize], + // Some hash functions allow inputs which are less than the generic parameters, others don't. + variable_length: bool, + // Make the source code specialized for a given expected input size. + source: impl Fn(usize) -> String, + // Rust implementation of the hash function. + hash: fn(&[u8]) -> [u8; N], +) { + for max_len in max_lengths { + let max_len = *max_len; + // The maximum length is used to pick the generic version of the method. + let source = source(max_len); + // Hash functions runs differently depending on whether the code is unconstrained or not. + for force_brillig in [false, true] { + let length_strategy = + if variable_length { (0..=max_len).boxed() } else { Just(max_len).boxed() }; + // The actual input length can be up to the maximum. + let strategy = length_strategy + .prop_flat_map(|len| prop::collection::vec(any::(), len)) + .prop_map(move |mut msg| { + // The output is the hash of the data as it is. + let output = hash(&msg); + + // The input has to be padded to the maximum length. + let msg_size = msg.len(); + msg.resize(max_len, 0u8); + + let mut inputs = vec![("input", bytes_input(&msg))]; + + // Omit the `message_size` if the hash function doesn't support it. + if variable_length { + inputs.push(( + "message_size", + InputValue::Field(FieldElement::from(msg_size)), + )); + } + + SnippetInputOutput::new(inputs, bytes_input(&output)).with_description(format!( + "force_brillig = {force_brillig}, max_len = {max_len}" + )) + }) + .boxed(); + + run_snippet_proptest(source.clone(), force_brillig, strategy); + } + } +} + +/// This is just a simple test to check that property testing works. +#[test] +fn fuzz_basic() { + let program = "fn main(init: u32) -> pub u32 { + let mut x = init; + for i in 0 .. 6 { + x += i; + } + x + }"; + + let strategy = any::() + .prop_map(|init| { + let init = init / 2; + SnippetInputOutput::new( + vec![("init", InputValue::Field(init.into()))], + InputValue::Field((init + 15).into()), + ) + }) + .boxed(); + + run_snippet_proptest(program.to_string(), false, strategy); +} + +#[test] +fn fuzz_keccak256_equivalence() { + run_hash_proptest( + // XXX: Currently it fails with inputs >= 135 bytes + &[0, 1, 100, 134], + true, + |max_len| { + format!( + "fn main(input: [u8; {max_len}], message_size: u32) -> pub [u8; 32] {{ + std::hash::keccak256(input, message_size) + }}" + ) + }, + |data| sha3::Keccak256::digest(data).into(), + ); +} + +#[test] +#[should_panic] // Remove once fixed +fn fuzz_keccak256_equivalence_over_135() { + run_hash_proptest( + &[135, 150], + true, + |max_len| { + format!( + "fn main(input: [u8; {max_len}], message_size: u32) -> pub [u8; 32] {{ + std::hash::keccak256(input, message_size) + }}" + ) + }, + |data| sha3::Keccak256::digest(data).into(), + ); +} + +#[test] +fn fuzz_sha256_equivalence() { + run_hash_proptest( + &[0, 1, 200, 511, 512], + true, + |max_len| { + format!( + "fn main(input: [u8; {max_len}], message_size: u64) -> pub [u8; 32] {{ + std::hash::sha256_var(input, message_size) + }}" + ) + }, + |data| sha2::Sha256::digest(data).into(), + ); +} + +#[test] +fn fuzz_sha512_equivalence() { + run_hash_proptest( + &[0, 1, 200], + false, + |max_len| { + format!( + "fn main(input: [u8; {max_len}]) -> pub [u8; 64] {{ + std::hash::sha512::digest(input) + }}" + ) + }, + |data| sha2::Sha512::digest(data).into(), + ); +} + +#[test] +fn fuzz_poseidon2_equivalence() { + use bn254_blackbox_solver::poseidon_hash; + + // Test empty, small, then around the RATE value, then bigger inputs. + for max_len in [0, 1, 3, 4, 100] { + let source = format!( + "fn main(input: [Field; {max_len}], message_size: u32) -> pub Field {{ + std::hash::poseidon2::Poseidon2::hash(input, message_size) + }}" + ); + + let strategy = (0..=max_len) + .prop_flat_map(field_vec_strategy) + .prop_map(move |mut msg| { + let output = poseidon_hash(&msg, msg.len() < max_len).expect("failed to hash"); + + // The input has to be padded to the maximum length. + let msg_size = msg.len(); + msg.resize(max_len, FieldElement::from(0u64)); + + let inputs = vec![ + ("input", InputValue::Vec(vecmap(msg, InputValue::Field))), + ("message_size", InputValue::Field(FieldElement::from(msg_size))), + ]; + + SnippetInputOutput::new(inputs, InputValue::Field(output)) + .with_description(format!("max_len = {max_len}")) + }) + .boxed(); + + run_snippet_proptest(source.clone(), false, strategy); + } +} + +#[test] +fn fuzz_poseidon_equivalence() { + use ark_ff_v04::{BigInteger, PrimeField}; + use light_poseidon::{Poseidon, PoseidonHasher}; + + let poseidon_hash = |inputs: &[FieldElement]| { + let mut poseidon = Poseidon::::new_circom(inputs.len()).unwrap(); + let frs: Vec = inputs + .iter() + .map(|f| ark_bn254_v04::Fr::from_be_bytes_mod_order(&f.to_be_bytes())) + .collect::>(); + let hash = poseidon.hash(&frs).expect("failed to hash"); + FieldElement::from_be_bytes_reduce(&hash.into_bigint().to_bytes_be()) + }; + + // Noir has hashes up to length 16, but the reference library won't work with more than 12. + for len in 1..light_poseidon::MAX_X5_LEN { + let source = format!( + "fn main(input: [Field; {len}]) -> pub Field {{ + let h1 = std::hash::poseidon::bn254::hash_{len}(input); + let h2 = {{ + let mut hasher = std::hash::poseidon::PoseidonHasher::default(); + input.hash(&mut hasher); + hasher.finish() + }}; + assert_eq(h1, h2); + h1 + }}" + ); + + let strategy = field_vec_strategy(len) + .prop_map(move |msg| { + let output = poseidon_hash(&msg); + let inputs = vec![("input", InputValue::Vec(vecmap(msg, InputValue::Field)))]; + + SnippetInputOutput::new(inputs, InputValue::Field(output)) + .with_description(format!("len = {len}")) + }) + .boxed(); + + run_snippet_proptest(source.clone(), false, strategy); + } +} + +fn bytes_input(bytes: &[u8]) -> InputValue { + InputValue::Vec( + bytes.iter().map(|b| InputValue::Field(FieldElement::from(*b as u32))).collect(), + ) +} + +fn field_vec_strategy(len: usize) -> impl Strategy> { + // Generate Field elements from random 32 byte vectors. + let field = prop::collection::vec(any::(), 32) + .prop_map(|bytes| FieldElement::from_be_bytes_reduce(&bytes)); + + prop::collection::vec(field, len) +} diff --git a/tooling/nargo_cli/tests/stdlib-tests.rs b/tooling/nargo_cli/tests/stdlib-tests.rs new file mode 100644 index 00000000000..048de33f24c --- /dev/null +++ b/tooling/nargo_cli/tests/stdlib-tests.rs @@ -0,0 +1,190 @@ +//! Execute unit tests in the Noir standard library. +#![allow(clippy::items_after_test_module)] +use clap::Parser; +use fm::FileManager; +use nargo::foreign_calls::DefaultForeignCallBuilder; +use nargo::PrintOutput; +use noirc_driver::{check_crate, file_manager_with_stdlib, CompileOptions}; +use noirc_frontend::hir::FunctionNameMatch; +use std::io::Write; +use std::{collections::BTreeMap, path::PathBuf}; + +use nargo::{ + ops::{report_errors, run_test, TestStatus}, + package::{Package, PackageType}, + parse_all, prepare_package, +}; +use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; +use test_case::test_matrix; + +#[derive(Parser, Debug)] +#[command(ignore_errors = true)] +pub struct Options { + /// Test name to filter for. + /// + /// First is assumed to be `run_stdlib_tests` and the second the of the stdlib tests, e.g.: + /// + /// ```text + /// cargo test -p nargo_cli --test stdlib-tests -- run_stdlib_tests sha256 + /// ``` + args: Vec, +} + +impl Options { + pub fn function_name_match(&self) -> FunctionNameMatch { + match self.args.as_slice() { + [_test_name, lib] => FunctionNameMatch::Contains(lib.as_str()), + _ => FunctionNameMatch::Anything, + } + } +} + +/// Inliner aggressiveness results in different SSA. +/// Inlining happens if `inline_cost - retain_cost < aggressiveness` (see `inlining.rs`). +/// NB the CLI uses maximum aggressiveness. +/// +/// Even with the same inlining aggressiveness, forcing Brillig can trigger different behaviour. +#[test_matrix( + [false, true], + [i64::MIN, 0, i64::MAX] +)] +fn run_stdlib_tests(force_brillig: bool, inliner_aggressiveness: i64) { + let opts = Options::parse(); + + 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: "stdlib".parse().unwrap(), + dependencies: BTreeMap::new(), + expression_width: None, + }; + + let (mut context, dummy_crate_id) = + prepare_package(&file_manager, &parsed_files, &dummy_package); + + let result = check_crate(&mut context, dummy_crate_id, &Default::default()); + 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(), + opts.function_name_match(), + ); + + let test_report: Vec<(String, TestStatus)> = test_functions + .into_iter() + .map(|(test_name, test_function)| { + let pedantic_solving = true; + let status = run_test( + &bn254_blackbox_solver::Bn254BlackBoxSolver(pedantic_solving), + &mut context, + &test_function, + PrintOutput::Stdout, + &CompileOptions { force_brillig, inliner_aggressiveness, ..Default::default() }, + |output, base| { + DefaultForeignCallBuilder::default().with_output(output).build_with_base(base) + }, + ); + (test_name, status) + }) + .collect(); + + assert!(!test_report.is_empty(), "Could not find any tests within the stdlib"); + display_test_report(&file_manager, &dummy_package, &CompileOptions::default(), &test_report); + assert!(test_report.iter().all(|(_, status)| !status.failed())); +} + +// This code is copied from `src/cli/test_cmd.rs`. +// This should be abstracted into a proper test runner at some point. +fn display_test_report( + file_manager: &FileManager, + package: &Package, + compile_options: &CompileOptions, + test_report: &[(String, TestStatus)], +) { + let writer = StandardStream::stderr(ColorChoice::Always); + let mut writer = writer.lock(); + + 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"); + + match &test_status { + TestStatus::Pass { .. } => { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Green))) + .expect("Failed to set color"); + writeln!(writer, "ok").expect("Failed to write to stderr"); + } + TestStatus::Fail { message, error_diagnostic } => { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Red))) + .expect("Failed to set color"); + writeln!(writer, "FAIL\n{message}\n").expect("Failed to write to stderr"); + if let Some(diag) = error_diagnostic { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[diag.clone()], + compile_options.deny_warnings, + compile_options.silence_warnings, + ); + } + } + TestStatus::Skipped { .. } => { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Yellow))) + .expect("Failed to set color"); + writeln!(writer, "skipped").expect("Failed to write to stderr"); + } + TestStatus::CompileError(err) => { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[err.clone()], + compile_options.deny_warnings, + compile_options.silence_warnings, + ); + } + } + writer.reset().expect("Failed to reset writer"); + } + + write!(writer, "[{}] ", package.name).expect("Failed to write to stderr"); + + 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"); + writer.reset().expect("Failed to reset writer"); + writeln!(writer).expect("Failed to write to stderr"); + } else { + let count_passed = count_all - count_failed; + let plural_failed = if count_failed == 1 { "" } else { "s" }; + let plural_passed = if count_passed == 1 { "" } else { "s" }; + + if count_passed != 0 { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Green))) + .expect("Failed to set color"); + write!(writer, "{count_passed} test{plural_passed} passed, ",) + .expect("Failed to write to stderr"); + } + + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red))).expect("Failed to set color"); + writeln!(writer, "{count_failed} test{plural_failed} failed") + .expect("Failed to write to stderr"); + writer.reset().expect("Failed to reset writer"); + } +} diff --git a/tooling/nargo_fmt/Cargo.toml b/tooling/nargo_fmt/Cargo.toml new file mode 100644 index 00000000000..710519712a2 --- /dev/null +++ b/tooling/nargo_fmt/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "nargo_fmt" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[lints] +workspace = true + +[dependencies] +noirc_frontend.workspace = true +serde.workspace = true +toml.workspace = true +thiserror.workspace = true + +[dev-dependencies] +similar-asserts.workspace = true diff --git a/tooling/nargo_fmt/build.rs b/tooling/nargo_fmt/build.rs new file mode 100644 index 00000000000..a95cbe16525 --- /dev/null +++ b/tooling/nargo_fmt/build.rs @@ -0,0 +1,96 @@ +use std::fs::File; +use std::io::Write; +use std::path::{Path, PathBuf}; + +fn main() { + let out_dir = std::env::var("OUT_DIR").unwrap(); + let destination = Path::new(&out_dir).join("execute.rs"); + let mut test_file = File::create(destination).unwrap(); + + // Try to find the directory that Cargo sets when it is running; otherwise fallback to assuming the CWD + // is the root of the repository and append the crate path + let manifest_dir = match std::env::var("CARGO_MANIFEST_DIR") { + Ok(dir) => PathBuf::from(dir), + Err(_) => std::env::current_dir().unwrap().join("tooling").join("nargo_fmt"), + }; + let test_dir = manifest_dir.join("tests"); + + generate_formatter_tests(&mut test_file, &test_dir); +} + +fn generate_formatter_tests(test_file: &mut File, test_data_dir: &Path) { + let inputs_dir = test_data_dir.join("input"); + let outputs_dir = test_data_dir.join("expected"); + + let test_case_files = + std::fs::read_dir(inputs_dir).unwrap().flatten().filter(|c| c.path().is_file()); + + for file in test_case_files { + let file_path = file.path(); + let file_name = file_path.file_name().unwrap(); + let test_name = file_path.file_stem().unwrap().to_str().unwrap(); + + if test_name.contains('-') { + panic!( + "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" + ); + }; + + let input_source_path = file.path(); + let input_source = std::fs::read_to_string(input_source_path).unwrap(); + + let config = input_source + .lines() + .flat_map(|line| line.strip_prefix("//@")) + .collect::>() + .join("\n"); + + let output_source_path = outputs_dir.join(file_name).display().to_string(); + let output_source = + std::fs::read_to_string(output_source_path.clone()).unwrap_or_else(|_| { + panic!("expected output source at {:?} was not found", &output_source_path) + }); + + write!( + test_file, + r##" + #[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 config = nargo_fmt::Config::of("{config}").unwrap(); + let fmt_text = nargo_fmt::format(input, parsed_module, &config); + + if std::env::var("UPDATE_EXPECT").is_ok() {{ + std::fs::write("{output_source_path}", fmt_text.clone()).unwrap(); + }} + + similar_asserts::assert_eq!(fmt_text, expected_output); + }} + "## + ) + .expect("Could not write templated test file."); + + 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/chunks.rs b/tooling/nargo_fmt/src/chunks.rs new file mode 100644 index 00000000000..fcef261284d --- /dev/null +++ b/tooling/nargo_fmt/src/chunks.rs @@ -0,0 +1,1047 @@ +//! This module has all the logic to format a series of chunks (a piece of text) in a way +//! that we (almost always) never exceed the configurable maximum line width. +//! +//! It's heavily inspired by this excellent blog post: +//! +//! https://yorickpeterse.com/articles/how-to-write-a-code-formatter/ +//! +//! However, some changes were introduces to handle comments and other particularities of Noir. +use std::ops::Deref; + +use noirc_frontend::token::Token; + +use super::Formatter; + +/// A text chunk. It precomputes the text width and whether it has newlines. +#[derive(Debug)] +pub(crate) struct TextChunk { + pub(crate) string: String, + pub(crate) width: usize, + pub(crate) has_newlines: bool, +} + +impl TextChunk { + pub(crate) fn new(string: String) -> Self { + TextChunk { + width: string.chars().count(), + has_newlines: string.chars().any(|char| char == '\n'), + string, + } + } +} + +/// A chunk can either be text or a directive that instructs the formatter to do something +/// (for example: increase or decrease the current indentation). +#[derive(Debug)] +pub(crate) enum Chunk { + /// A text chunk. It might contain leading comments. + Text(TextChunk), + /// A text chunk that should be printed unmodified (used for `quote { ... }` contents). + Verbatim(TextChunk), + /// A trailing comma that's only written if we decide to format chunks in multiple lines + /// (for example for a call we'll add a trailing comma to the last argument). + TrailingComma, + /// A trailing comment (happens at the end of a line, and always after something else have been written). + TrailingComment(TextChunk), + /// A leading comment. Happens at the beginning of a line. + LeadingComment(TextChunk), + /// A group of chunks. + Group(ChunkGroup), + /// Write a line (or two) if we decide to format chunks in multiple lines, otherwise do nothing. + Line { two: bool }, + /// Writes a space if we can write a group in one line, otherwise writes a line. + /// However, a space might be written if `one_chunk_per_line` of a Chunks object is set to false. + SpaceOrLine, + /// Command to increase the current indentation. + IncreaseIndentation, + /// Command to decrease the current indentation. + DecreaseIndentation, + /// Push the current indentation to the indentation stack. + PushIndentation, + /// Set the current indentation by popping it from the indentation stack. + PopIndentation, +} + +impl Chunk { + pub(crate) fn width(&self) -> usize { + match self { + Chunk::Text(chunk) + | Chunk::Verbatim(chunk) + | Chunk::TrailingComment(chunk) + | Chunk::LeadingComment(chunk) => chunk.width, + Chunk::Group(group) => group.width(), + Chunk::SpaceOrLine => 1, + Chunk::Line { .. } + | Chunk::IncreaseIndentation + | Chunk::DecreaseIndentation + | Chunk::TrailingComma + | Chunk::PushIndentation + | Chunk::PopIndentation => 0, + } + } + + /// Computes the width of this chunk considering it's inside an ExpressionList. + /// The only thing that changes here compared to `width` is that a LambdaAsLastExpressionInList's + /// width is considered to be only the first line, so we can avoid splitting the entire call + /// arguments into separate lines. + pub(crate) fn width_inside_an_expression_list(&self) -> usize { + if let Chunk::Group(group) = &self { + if let GroupKind::LambdaAsLastExpressionInList { first_line_width, .. } = &group.kind { + return *first_line_width; + } + } + + self.width() + } + + pub(crate) fn has_newlines(&self) -> bool { + match self { + Chunk::Text(chunk) + | Chunk::Verbatim(chunk) + | Chunk::TrailingComment(chunk) + | Chunk::LeadingComment(chunk) => chunk.has_newlines, + Chunk::Group(group) => group.has_newlines(), + Chunk::TrailingComma + | Chunk::Line { .. } + | Chunk::SpaceOrLine + | Chunk::IncreaseIndentation + | Chunk::DecreaseIndentation + | Chunk::PushIndentation + | Chunk::PopIndentation => false, + } + } + + /// Returns the current chunk as a Group, if it is one. Otherwise returns None. + pub(crate) fn group(self) -> Option { + if let Chunk::Group(group) = self { + Some(group) + } else { + None + } + } +} + +#[derive(Debug)] +pub(crate) struct ChunkGroup { + pub(crate) chunks: Vec, + + /// If `true`, when formatting in multiple lines, and after a SpaceOrLine, + /// a line will be written. + /// If `false`, when formatting in multiple lines, and after a SpaceOrLine, + /// a space will be inserted and the next chunk will go in the same line if + /// it fits that line. + /// + /// This is used to, for example, control how arrays are formatted. If each + /// element is short, we'll format the array like this: + /// + /// [ + /// 1, 2, 3, + /// 4, 5 + /// ] + /// + /// but if one of the elements is long, each one will go in a separate line: + /// + /// ```text + /// [ + /// 1, + /// 1234567890123, + /// 3 + /// ] + /// ``` + pub(crate) one_chunk_per_line: bool, + + /// If true, regardless of this group's chunks, this group will be formatted in + /// multiple lines. + /// This is set to true when, for example, we format a block that has at least + /// two statements: we always want to show that in multiple lines. + pub(crate) force_multiple_lines: bool, + + /// Groups can be tagged. For example we tag all consequences and alternative blocks + /// of an `if` expression. If we determine one of them needs to be formatted in multiple + /// lines, we find all other chunks with the same tag and mark them too to be formatted + /// in multiple lines. + pub(crate) tag: Option, + + /// The kind of this group. Some group kinds are formatted in a special way + /// (mainly lambda arguments that are the last expression in a list). + pub(crate) kind: GroupKind, + + /// This name is a bit long and explicit, but it's to make things clearer: + /// if we determine that this group needs to be formatted in multiple lines, + /// children groups with the same tag will also be formatted in multiple lines. + /// + /// This is used for example in infix expressions like `a + b + c + d`, where if we + /// determine that `a + b` needs to be formatted in multiple lines, we want the entire + /// tree (of those infix expressions) to be formatted in multiple lines. + pub(crate) force_multiline_on_children_with_same_tag_if_multiline: bool, +} + +impl ChunkGroup { + pub(crate) fn new() -> Self { + Self { + chunks: Vec::new(), + one_chunk_per_line: true, + force_multiple_lines: false, + tag: None, + kind: GroupKind::Regular, + force_multiline_on_children_with_same_tag_if_multiline: false, + } + } + + /// Appends a text to this group. + /// If the last chunk in this group is a text, no new chunk is inserted and + /// instead the last text chunk is extended. + pub(crate) fn text(&mut self, chunk: TextChunk) { + if chunk.width == 0 { + return; + } + + if let Some(Chunk::Text(text_chunk)) = self.chunks.last_mut() { + text_chunk.string.push_str(&chunk.string); + text_chunk.width += chunk.width; + text_chunk.has_newlines |= chunk.has_newlines; + } else { + self.push(Chunk::Text(chunk)); + } + } + + /// Appends a verbatim text chunk to this group. + pub(crate) fn verbatim(&mut self, chunk: TextChunk) { + if chunk.width == 0 { + return; + } + + self.push(Chunk::Verbatim(chunk)); + } + + /// Appends a single space to this group by reading it from the given formatter. + pub(crate) fn space(&mut self, formatter: &mut ChunkFormatter<'_, '_>) { + self.text(formatter.chunk(|formatter| { + formatter.write_space(); + })); + } + + /// Appends a semicolon to this group by reading it from the given formatter. + /// This will actually end up attaching the semicolon to the last text in this + /// group so that we don't end up with stray semicolons. + pub(crate) fn semicolon(&mut self, formatter: &mut ChunkFormatter<'_, '_>) { + self.text_attached_to_last_group(formatter.chunk(|formatter| { + formatter.write_semicolon(); + })); + } + + /// Appends a TextChunk to this chunks chunks. However, if the last chunk is a group, + /// it's appended to that group's last text. + pub(crate) fn text_attached_to_last_group(&mut self, chunk: TextChunk) { + if chunk.width == 0 { + return; + } + + if let Some(Chunk::Group(group)) = self.chunks.last_mut() { + group.text(chunk); + } else { + self.text(chunk); + } + } + + /// Appends a trailing comment (it's formatted slightly differently than a regular text chunk). + pub(crate) fn trailing_comment(&mut self, chunk: TextChunk) { + if chunk.width > 0 { + self.push(Chunk::TrailingComment(chunk)); + } + } + + /// Appends a leading comment (it's formatted slightly differently than a regular text chunk). + pub(crate) fn leading_comment(&mut self, chunk: TextChunk) { + if chunk.width > 0 { + self.push(Chunk::LeadingComment(chunk)); + } + } + + /// Appends a trailing comma (will only show up if the group is formatted in multiple lines). + pub(crate) fn trailing_comma(&mut self) { + self.push(Chunk::TrailingComma); + } + + /// Appends another group as a nested group. + pub(crate) fn group(&mut self, group: ChunkGroup) { + self.push(Chunk::Group(group)); + } + + /// Append one line to this chunk. + pub(crate) fn line(&mut self) { + self.lines(false); + } + + /// Append one or two lines to this chunk. + pub(crate) fn lines(&mut self, two: bool) { + self.push(Chunk::Line { two }); + } + + /// Appends a SpaceOrLine chunk, which means that it's a space when this group is + /// formatted in a single line, or a line when it's formatted in multiple lines. + pub(crate) fn space_or_line(&mut self) { + self.push(Chunk::SpaceOrLine); + } + + pub(crate) fn increase_indentation(&mut self) { + self.push(Chunk::IncreaseIndentation); + } + + pub(crate) fn decrease_indentation(&mut self) { + self.push(Chunk::DecreaseIndentation); + } + + pub(crate) fn push_indentation(&mut self) { + self.push(Chunk::PushIndentation); + } + + pub(crate) fn pop_indentation(&mut self) { + self.push(Chunk::PopIndentation); + } + + pub(crate) fn push(&mut self, chunk: Chunk) { + self.chunks.push(chunk); + } + + pub(crate) fn width(&self) -> usize { + self.chunks.iter().map(|chunk| chunk.width()).sum() + } + + pub(crate) fn expression_list_width(&self) -> usize { + self.chunks.iter().map(|chunk| chunk.width_inside_an_expression_list()).sum() + } + + pub(crate) fn has_newlines(&self) -> bool { + self.force_multiple_lines || self.chunks.iter().any(|chunk| chunk.has_newlines()) + } + + /// Determines if this group has a LambdaAsLastExpressionInList chunk. + /// Note that if this group is a MethodCall, this is checked for the ExpressionList group + /// inside it. + pub(crate) fn has_lambda_as_last_expression_in_list(&self) -> bool { + self.chunks.iter().any(|chunk| { + if let Chunk::Group(group) = chunk { + if self.kind.is_method_call() && group.kind.is_expression_list() { + group.has_lambda_as_last_expression_in_list() + } else { + matches!(group.kind, GroupKind::LambdaAsLastExpressionInList { .. }) + } + } else { + false + } + }) + } + + /// Finds the `LambdaAsLastExpressionInList` associated to this group and sets its indentation + /// to the given value. + pub(crate) fn set_lambda_as_last_expression_in_list_indentation( + &mut self, + indentation_to_set: i32, + ) { + for chunk in self.chunks.iter_mut() { + if let Chunk::Group(group) = chunk { + if self.kind.is_method_call() && group.kind.is_expression_list() { + group.set_lambda_as_last_expression_in_list_indentation(indentation_to_set); + } else if let GroupKind::LambdaAsLastExpressionInList { indentation, .. } = + &mut group.kind + { + if indentation.is_none() { + *indentation = Some(indentation_to_set); + } + } + } + } + } + + /// Before writing a Chunks object in multiple lines, create a new one where `TrailingComma` + /// is turned into `Text`. Because Chunks will glue two consecutive `Text`s together, if we + /// have two chunks `Text("123"), TrailingComma`, we'll consider the entire string "123," + /// when deciding whether we can still write in the current line or not. + pub(crate) fn prepare_for_multiple_lines(self) -> ChunkGroup { + let mut group = ChunkGroup { chunks: Vec::new(), ..self }; + + for chunk in self.chunks { + match chunk { + Chunk::Text(chunk) => group.text(chunk), + Chunk::Verbatim(chunk) => group.verbatim(chunk), + Chunk::TrailingComma => { + // If there's a trailing comma after a group, append the text to that group + // so that it glues with the last text present there (if any) + group.add_trailing_comma_to_last_text(); + } + Chunk::TrailingComment(chunk) => group.trailing_comment(chunk), + Chunk::LeadingComment(chunk) => group.leading_comment(chunk), + Chunk::Group(inner_group) => group.group(inner_group), + Chunk::Line { two } => group.lines(two), + Chunk::SpaceOrLine => group.space_or_line(), + Chunk::IncreaseIndentation => group.increase_indentation(), + Chunk::DecreaseIndentation => group.decrease_indentation(), + Chunk::PushIndentation => group.push_indentation(), + Chunk::PopIndentation => group.pop_indentation(), + } + } + group + } + + fn add_trailing_comma_to_last_text(&mut self) { + if let Some(Chunk::Group(group)) = self.chunks.last_mut() { + group.add_trailing_comma_to_last_text(); + } else { + self.text(TextChunk::new(",".to_string())); + } + } + + /// Returns the width of text until we hit a Line or LineOrSpace, together + /// with whether we hit a Line or LineOrSpace. + fn width_until_line(&self) -> (usize, bool) { + let mut width = 0; + for chunk in &self.chunks { + match chunk { + Chunk::Text(text_chunk) + | Chunk::Verbatim(text_chunk) + | Chunk::TrailingComment(text_chunk) + | Chunk::LeadingComment(text_chunk) => { + width += text_chunk.width; + } + Chunk::Group(chunk_group) => { + let (group_width, hit_line) = chunk_group.width_until_line(); + width += group_width; + if hit_line { + return (width, true); + } + } + Chunk::Line { .. } | Chunk::SpaceOrLine => { + return (width, true); + } + Chunk::IncreaseIndentation + | Chunk::DecreaseIndentation + | Chunk::PushIndentation + | Chunk::PopIndentation + | Chunk::TrailingComma => (), + } + } + + (width, false) + } + + fn first_group(&self) -> Option<&ChunkGroup> { + self.chunks + .iter() + .filter_map(|chunk| if let Chunk::Group(group) = chunk { Some(group) } else { None }) + .next() + } + + fn has_expression_list_or_method_call_group(&self) -> bool { + for chunk in &self.chunks { + if let Chunk::Group(group) = chunk { + if group.kind.is_expression_list() || group.kind.is_method_call() { + return true; + } + } + } + + false + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) struct GroupTag(usize); + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) enum GroupKind { + /// Most chunks are regular chunks and are not of interest. + Regular, + /// This is a chunk that has a list of expression in it, for example: + /// a call, a method call, an array literal, a tuple literal, etc. + /// `prefix_width` is the width of whatever is before the actual expression list. + /// For example, for an array this is 1 (for "["), for a slice it's 2 ("&["), etc. + ExpressionList { prefix_width: usize, expressions_count: usize }, + /// This is a chunk for a lambda argument that is the last expression of an ExpressionList. + /// `first_line_width` is the width of the first line of the lambda argument: the parameters + /// list and the left bracket. + LambdaAsLastExpressionInList { first_line_width: usize, indentation: Option }, + /// The body of a lambda. + /// We track this as a group kind so that when we have to write it, if it doesn't + /// fit in the current line and it's not a block, instead of splitting that expression + /// somewhere that's probably undesired, we'll "turn it" into a block + /// (write the "{" and "}" delimiters) and write the lambda body in the next line. + LambdaBody { + block_statement_count: Option, + has_comments: bool, + lambda_has_return_type: bool, + }, + /// A method call. + /// We track all this information to see, if we end up needing to format this call + /// in multiple lines, if we can write everything up to the left parentheses (inclusive) + /// in one line, and just the call arguments in multiple lines. + MethodCall { + /// This is the width of the group until the left parenthesis (inclusive). + width_until_left_paren_inclusive: usize, + /// Are there newlines before the left parentheses in this group? + has_newlines_before_left_paren: bool, + /// Is this method call the left-hand side of a call chain? If so, this is true, + /// otherwise this is false an it means it's the outermost call. + lhs: bool, + }, + /// The value of an assignment or let statement. We know this is the last group in a chunk so + /// if it doesn't fit in the current line but it fits in the next line, we can + /// write a newline, indent, and put it there (instead of writing the value in + /// multiple lines). + AssignValue, +} + +impl GroupKind { + fn is_method_call(&self) -> bool { + matches!(self, GroupKind::MethodCall { .. }) + } + + fn is_expression_list(&self) -> bool { + matches!(self, GroupKind::ExpressionList { .. }) + } +} + +/// Interface for creating TextChunks. +pub(crate) struct ChunkFormatter<'a, 'b>(&'b mut Formatter<'a>); + +impl<'a, 'b> ChunkFormatter<'a, 'b> { + pub(crate) fn new(formatter: &'b mut Formatter<'a>) -> Self { + Self(formatter) + } + + /// Stops writing to the current buffer for the duration of the `f` call, which takes + /// a formatter to write to. Then, returns a `TextChunk` with the written text. + /// + /// This allows a caller to format pieces of code and then pre-process them before + /// writing to the main buffer. + pub(crate) fn chunk(&mut self, f: impl FnOnce(&mut Formatter)) -> TextChunk { + let previous_buffer = std::mem::take(&mut self.0.buffer); + let previous_indentation = self.0.indentation; + self.0.indentation = 0; + + f(self.0); + + self.0.indentation = previous_indentation; + + let buffer = std::mem::replace(&mut self.0.buffer, previous_buffer); + TextChunk::new(buffer.contents()) + } + + /// Stops writing to the current buffer, skips comments and whitespaces (formatting them) + /// and returns the formatted result as a `TextChunk`. + pub(crate) fn skip_comments_and_whitespace_chunk(&mut self) -> TextChunk { + self.chunk(|formatter| { + formatter.skip_comments_and_whitespace(); + }) + } + + pub(super) fn new_group_tag(&mut self) -> GroupTag { + self.0.new_group_tag() + } + + pub(super) fn bump(&mut self) -> Token { + self.0.bump() + } +} + +/// Treating a `ChunkFormatter` as a `Formatter` in read-only mode is always fine, +/// and reduces some boilerplate. +impl<'a, 'b> Deref for ChunkFormatter<'a, 'b> { + type Target = Formatter<'b>; + + fn deref(&self) -> &Self::Target { + self.0 + } +} + +impl<'a> Formatter<'a> { + /// Returns an object that has a `chunk` method to get a TextChunk. + /// This method exists so that we can't mix the two operation modes: + /// using the formatter directly while writing to the buffer, or creating text chunks. + pub(super) fn chunk_formatter(&mut self) -> ChunkFormatter<'a, '_> { + ChunkFormatter::new(self) + } + + /// Main interface to format a chunk group. + /// Here it's determined if the chunk will group in a single line or multiple lines. + pub(super) fn format_chunk_group(&mut self, group: ChunkGroup) { + let previous_indentation = self.indentation; + self.format_chunk_group_impl(group); + self.indentation = previous_indentation; + } + + pub(super) fn format_chunk_group_impl(&mut self, group: ChunkGroup) { + if let GroupKind::LambdaAsLastExpressionInList { indentation: Some(indentation), .. } = + group.kind + { + let previous_indentation = self.indentation; + self.indentation = indentation; + self.format_chunks_group_impl_without_lambda_handling(group); + self.indentation = previous_indentation; + } else { + self.format_chunks_group_impl_without_lambda_handling(group); + } + } + + pub(super) fn format_chunks_group_impl_without_lambda_handling( + &mut self, + mut group: ChunkGroup, + ) { + let chunks_width = group.width(); + let total_width = self.current_line_width() + chunks_width; + + if total_width > self.max_width { + // If this is a method call that doesn't fit in the current line, we check if + // everything that follows up to the left parentheses fits in the current line. + // If so, we write that and we'll end up formatting the arguments in multiple + // lines, instead of splitting this entire call chain in multiple lines. + // + // For example, a call like this: + // + // foo.bar.baz.qux(1) + // + // if it exceeds the maximum width, will end up being formatted like this: + // + // foo.bar.baz.qux( + // 1, + // ) + // + // instead of like this (many more lines): + // + // foo + // .bar + // .baz + // .qux(1) + // + // This is something that rustfmt seems to do too. + if let GroupKind::MethodCall { + width_until_left_paren_inclusive, + has_newlines_before_left_paren: false, + lhs: false, + } = group.kind + { + let total_width = self.current_line_width() + width_until_left_paren_inclusive; + if total_width <= self.max_width { + // Check if this method call has another call or method call nested in it. + // If not, it means tis is the last nested call and after it we'll need to start + // writing at least one closing parentheses. So the argument list will actually + // have one less character available for writing, and that's why we (temporarily) decrease + // max width. + let expression_list_group = group.first_group().unwrap(); + let has_expression_list_or_call_group = + expression_list_group.has_expression_list_or_method_call_group(); + if !has_expression_list_or_call_group { + self.max_width -= 1; + } + + // When a method call's group is formed, we indent after the first dot. But with that + // indentation, and the arguments indentation, we'll end up with too much indentation, + // so here we decrease it to compensate that. + self.decrease_indentation(); + self.format_chunk_group_in_one_line(group); + self.increase_indentation(); + + if !has_expression_list_or_call_group { + self.max_width += 1; + } + return; + } + } + + // If this is an expression list with a single expression, see if we can fit whatever + // comes next until a line in the current line. For example, if we have this: + // + // foo(bar(baz(1))) + // + // then `foo(...)` is an ExpressionList. We check if `foo(` fits in the current line. + // If yes, we write it in the current line and continue. Then we'll find `bar(...)`, + // which is also an ExpressionList, and if `bar(` fits the current line, we'll write it, + // etc. But we only do this if we have nested calls (nested expression lists, etc.) + // + // This is to avoid formatting the above like this: + // + // foo( + // bar( + // baz( + // 1, + // ), + // ), + // ) + // + // (rustfmt seems to do the same thing) + if let GroupKind::ExpressionList { prefix_width, expressions_count: 1 } = group.kind { + if let Some(inner_group) = group.first_group() { + if inner_group.kind.is_expression_list() || inner_group.kind.is_method_call() { + let total_width = self.current_line_width() + + prefix_width + + inner_group.width_until_line().0; + if total_width <= self.max_width { + self.decrease_indentation(); + self.format_chunk_group_in_one_line(group); + self.increase_indentation(); + return; + } + } + } + } + } + + if group.force_multiple_lines { + self.format_chunk_group_in_multiple_lines(group); + return; + } + + // if chunks.has_newlines() { + // When formatting an expression list we have to check if the last argument is a lambda, + // because we format that in a special way: + // 1. to compute the group width we'll consider only the `|...| {` part of the lambda + // 2. If it fits in a line, we'll format this expression list in a single line + // 3. However, an expression list is instructed to increase indentation after, say, + // `(` or `[` (depending on the expression list) and then the `{` part of a lambda + // will also increase the indentation, resulting in too much indentation. + // 4. For that reason we adjust the lambda to be formatted with the indentation + // we have right that (that is, that of the call that holds the lambda). + // We do that by setting the `indentation` field of the LambdaAsLastExpressionInList. + // + // Note that this logic is a bit complex because for method calls, the arguments list + // is in a group so all arguments can potentially be formatted in a single line, and + // that group has the `ExpressionList` kind. The method call itself has the `MethodCall` + // kind. So when determining the first line width of a method call with a lambda as + // the last argument we have to find the nested ExpressionList and do some nested calls. + if (group.kind.is_expression_list() || group.kind.is_method_call()) + && group.has_lambda_as_last_expression_in_list() + { + let chunks_width = group.expression_list_width(); + let total_width = self.current_line_width() + chunks_width; + if total_width <= self.max_width { + group.set_lambda_as_last_expression_in_list_indentation(self.indentation); + self.format_chunk_group_in_one_line(group); + return; + } + } + + if group.has_newlines() { + self.format_chunk_group_in_multiple_lines(group); + return; + } + + // Check if the group first in the remainder of the current line. + if total_width > self.max_width { + // If this chunk is the value of an assignment (either a normal assignment or a let statement) + // and it doesn't fit the current line, we check if it fits the next line with an increased + // indentation. + // + // That way this: + // + // let x = foo(1, 2); + // ^ + // assume the max width is here + // + // is formatted like this: + // + // let x = + // foo(1, 2); + // + // instead of: + // + // let x = foo( + // 1, + // 2, + // ) + if group.kind == GroupKind::AssignValue { + let total_width_next_line = + (self.indentation as usize + 1) * self.config.tab_spaces + chunks_width; + if total_width_next_line <= self.max_width { + // We might have trailing spaces + // (for example a space after the `=` of a let statement or an assignment) + self.trim_spaces(); + self.write_line_without_skipping_whitespace_and_comments(); + self.increase_indentation(); + self.write_indentation(); + self.format_chunk_group_in_one_line(group); + self.decrease_indentation(); + return; + } + } + + // If a lambda body doesn't fit in the current line and it's not a block, + // we can turn it into a block and write it in the next line, so its contents fit. + if let GroupKind::LambdaBody { block_statement_count: None, .. } = group.kind { + // Try to format it again in the next line, but we don't want to recurse + // infinitely so we change the group kind. + group.kind = GroupKind::Regular; + self.write("{"); + self.trim_spaces(); + self.increase_indentation(); + self.write_line_without_skipping_whitespace_and_comments(); + self.write_indentation(); + self.format_chunk_group_impl(group); + + // If this lambda was in an expression list and it was formatted in multiple + // lines, it might be that the trailing comma happened after the lambda body: + // + // foo( + // 1, + // |lambda| body, + // ) + // + // Because we attach commas to the last text to avoid splitting it, the body + // in this case is "body,", so if we end up writing it as a block it will + // look like this: + // + // foo( + // 1, + // |lambda| { + // body, + // } + // ) + // + // So, if after writing the body we find a comma (there will be at most one) + // we remove it, but place it after the right brace, so it looks like this: + // + // foo( + // 1, + // |lambda| { + // body + // }, + // ) + let comma_trimmed = self.trim_comma(); + self.decrease_indentation(); + self.write_line_without_skipping_whitespace_and_comments(); + self.write_indentation(); + self.write("}"); + if comma_trimmed { + self.write(","); + } + return; + } + + self.format_chunk_group_in_multiple_lines(group); + return; + } + + // At this point we determined we are going to write this group in a single line. + // If the current group is a lambda body that is a block with a single statement, like this: + // + // |x| { 1 + 2 } + // + // given that we determined the block fits the current line, if we remove the surrounding + // `{ .. }` it will still fit the current line, and reduce some noise from the code + // (this is what rustfmt seems to do too). + if let GroupKind::LambdaBody { + block_statement_count: Some(1), + has_comments: false, + lambda_has_return_type: false, + } = group.kind + { + self.format_lambda_body_removing_braces(group); + return; + } + + self.format_chunk_group_in_one_line(group); + } + + pub(super) fn format_chunk_group_in_one_line(&mut self, group: ChunkGroup) { + for chunk in group.chunks { + match chunk { + Chunk::Text(text_chunk) | Chunk::Verbatim(text_chunk) => { + self.write(&text_chunk.string); + } + Chunk::TrailingComment(text_chunk) | Chunk::LeadingComment(text_chunk) => { + self.write(&text_chunk.string); + self.write_space_without_skipping_whitespace_and_comments(); + } + Chunk::Group(chunks) => self.format_chunk_group_impl(chunks), + Chunk::SpaceOrLine => self.write_space_without_skipping_whitespace_and_comments(), + Chunk::IncreaseIndentation => self.increase_indentation(), + Chunk::DecreaseIndentation => self.decrease_indentation(), + Chunk::PushIndentation => self.push_indentation(), + Chunk::PopIndentation => self.pop_indentation(), + Chunk::TrailingComma | Chunk::Line { .. } => (), + } + } + } + + pub(super) fn format_chunk_group_in_multiple_lines(&mut self, group: ChunkGroup) { + let chunks = group.prepare_for_multiple_lines(); + + let mut last_was_space_or_line = false; + + for chunk in chunks.chunks { + if last_was_space_or_line { + if chunks.one_chunk_per_line { + self.write_line_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else { + // "+ 1" because we still need to add a space before the next chunk + if self.current_line_width() + chunk.width() + 1 > self.max_width { + self.write_line_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else { + self.write_space_without_skipping_whitespace_and_comments(); + } + } + } + + last_was_space_or_line = false; + + match chunk { + Chunk::Text(text_chunk) => { + if text_chunk.has_newlines { + self.write_chunk_lines(&text_chunk.string); + } else { + // If we didn't exceed the max width, but this chunk will, insert a newline, + // increase indentation and indent (the indentation will be undone + // after `format_chunks` finishes). + // This is the logic to automatically wrap a line when a ChunkGroup doesn't + // have Line or SpaceOrLine in it. + if self.current_line_width() <= self.max_width + && self.current_line_width() + text_chunk.width > self.max_width + && !self.buffer.ends_with_space() + { + self.write_line_without_skipping_whitespace_and_comments(); + self.increase_indentation(); + self.write_indentation(); + } + self.write(&text_chunk.string); + } + } + Chunk::Verbatim(text_chunk) => { + self.write(&text_chunk.string); + } + Chunk::TrailingComment(text_chunk) => { + self.write_chunk_lines(&text_chunk.string); + self.write_line_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } + Chunk::LeadingComment(text_chunk) => { + let ends_with_multiple_newlines = text_chunk.string.ends_with("\n\n"); + let ends_with_newline = + ends_with_multiple_newlines || text_chunk.string.ends_with('\n'); + self.write_chunk_lines(text_chunk.string.trim()); + + // Respect whether the leading comment had a newline before what comes next or not + if ends_with_multiple_newlines { + // Remove any indentation that could exist (we'll add it later) + self.buffer.trim_spaces(); + self.write_multiple_lines_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else if ends_with_newline { + self.write_line_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else { + self.write_space_without_skipping_whitespace_and_comments(); + } + } + Chunk::Group(mut group) => { + if chunks.force_multiline_on_children_with_same_tag_if_multiline + && chunks.tag == group.tag + { + group.force_multiple_lines = true; + group.force_multiline_on_children_with_same_tag_if_multiline = true; + } + + self.format_chunk_group_impl(group); + } + Chunk::Line { two } => { + if two { + self.write_multiple_lines_without_skipping_whitespace_and_comments(); + } else { + self.write_line_without_skipping_whitespace_and_comments(); + } + self.write_indentation(); + } + Chunk::SpaceOrLine => { + last_was_space_or_line = true; + } + Chunk::IncreaseIndentation => { + self.increase_indentation(); + } + Chunk::DecreaseIndentation => { + self.decrease_indentation(); + } + Chunk::PushIndentation => { + self.push_indentation(); + } + Chunk::PopIndentation => { + self.pop_indentation(); + } + Chunk::TrailingComma => { + unreachable!( + "TrailingComma should have been removed by `prepare_for_multiple_lines`" + ) + } + } + } + } + + fn format_lambda_body_removing_braces(&mut self, group: ChunkGroup) { + // Write to an intermediate string so we can remove the braces if needed. + let text_chunk = self.chunk_formatter().chunk(|formatter| { + formatter.format_chunk_group_in_one_line(group); + }); + let string = text_chunk.string; + + // Don't remove the braces if the lambda's body is a Semi expression. + if string.ends_with("; }") || string.ends_with("; },") { + self.write(&string); + return; + } + + let string = string.strip_prefix("{ ").unwrap(); + + // The lambda might have a trailing comma if it's inside an arguments list + if let Some(string) = string.strip_suffix(" },") { + self.write(string); + self.write(","); + } else { + let string = string.strip_suffix(" }").unwrap(); + self.write(string); + } + } + + /// Appends the string to the current buffer line by line, with some pre-checks. + fn write_chunk_lines(&mut self, string: &str) { + let lines: Vec<_> = string.lines().collect(); + + let mut index = 0; + while index < lines.len() { + let line = &lines[index]; + + // Don't indent the first line (it should already be indented). + // Also don't indent if the current line already has a space as the last char + // (it means it's already indented) + if index > 0 && !self.buffer.ends_with_space() { + self.write_line_without_skipping_whitespace_and_comments(); + // Only indent if the line doesn't start with a space. When that happens + // it's likely a block comment part that we don't want to modify. + if !line.starts_with(' ') { + self.write_indentation(); + } + } + + // If we already have a space in the buffer and the line starts with a space, + // don't repeat that space. + if self.buffer.ends_with_space() && line.starts_with(' ') { + self.write(line.trim_start()); + } else { + self.write(line); + } + + index += 1; + + // If a newline comes next too, write multiple lines to preserve original formatting + while index < lines.len() && lines[index].is_empty() { + self.write_multiple_lines_without_skipping_whitespace_and_comments(); + index += 1; + } + } + } + + /// Returns a new GroupTag that is unique compared to other `new_group_tag` calls. + pub(super) fn new_group_tag(&mut self) -> GroupTag { + let tag = GroupTag(self.group_tag_counter); + self.group_tag_counter += 1; + tag + } +} diff --git a/tooling/nargo_fmt/src/config.rs b/tooling/nargo_fmt/src/config.rs new file mode 100644 index 00000000000..488647c0b39 --- /dev/null +++ b/tooling/nargo_fmt/src/config.rs @@ -0,0 +1,87 @@ +use std::path::Path; + +use serde::{Deserialize, Serialize}; + +use crate::errors::ConfigError; + +macro_rules! config { + ($($field_name:ident: $field_ty:ty, $default_value:expr, $description:expr );+ $(;)*) => ( + pub struct Config { + $( + #[doc = $description] + pub $field_name: $field_ty + ),+ + } + + impl Config { + pub fn fill_from_toml(&mut self, toml: TomlConfig) { + $( + if let Some(value) = toml.$field_name { + self.$field_name = value; + } + )+ + } + } + + impl Default for Config { + fn default() -> Self { + Self { + $( + $field_name: $default_value, + )+ + } + } + } + + #[derive(serde::Deserialize, serde::Serialize, Clone)] + pub struct TomlConfig { + $( + #[doc = $description] + pub $field_name: Option<$field_ty> + ),+ + } + ) +} + +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"; + 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"; + single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else expressions"; + imports_granularity: ImportsGranularity, ImportsGranularity::Preserve, "How imports should be grouped into use statements."; + reorder_imports: bool, true, "Reorder imports alphabetically"; +} + +impl Config { + pub fn read(path: &Path) -> Result { + let config_path = path.join("noirfmt.toml"); + + let input = match std::fs::read_to_string(&config_path) { + Ok(input) => input, + Err(cause) if cause.kind() == std::io::ErrorKind::NotFound => String::new(), + Err(cause) => return Err(ConfigError::ReadFailed(config_path, cause)), + }; + + Self::of(&input) + } + + pub fn of(s: &str) -> Result { + let mut config = Self::default(); + let toml = toml::from_str(s).map_err(ConfigError::MalformedFile)?; + config.fill_from_toml(toml); + Ok(config) + } +} + +/// How imports should be grouped into use statements. +/// Imports will be merged or split to the configured level of granularity. +#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Eq)] +pub enum ImportsGranularity { + /// Do not change the granularity of any imports and preserve the original structure written by the developer. + Preserve, + /// Merge imports from the same crate into a single use statement. + Crate, +} diff --git a/tooling/nargo_fmt/src/errors.rs b/tooling/nargo_fmt/src/errors.rs new file mode 100644 index 00000000000..e0a1758ae0f --- /dev/null +++ b/tooling/nargo_fmt/src/errors.rs @@ -0,0 +1,12 @@ +use std::path::PathBuf; + +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ConfigError { + #[error("Cannot read file {0} - {1}")] + ReadFailed(PathBuf, std::io::Error), + + #[error("noirfmt.toml is badly formed, could not parse.\n\n {0}")] + MalformedFile(#[from] toml::de::Error), +} diff --git a/tooling/nargo_fmt/src/formatter.rs b/tooling/nargo_fmt/src/formatter.rs new file mode 100644 index 00000000000..4184ff288d7 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter.rs @@ -0,0 +1,312 @@ +use buffer::Buffer; +use noirc_frontend::{ + ast::Ident, + hir::resolution::errors::Span, + lexer::Lexer, + token::{Keyword, SpannedToken, Token}, + ParsedModule, +}; + +use crate::Config; + +mod alias; +mod attribute; +mod buffer; +mod comments_and_whitespace; +mod doc_comments; +mod expression; +mod function; +mod generics; +mod global; +mod impls; +mod item; +mod lvalue; +mod module; +mod path; +mod pattern; +mod statement; +mod structs; +mod trait_impl; +mod traits; +mod type_expression; +mod types; +mod use_tree; +mod use_tree_merge; +mod visibility; +mod where_clause; + +pub(crate) struct Formatter<'a> { + pub(crate) config: &'a Config, + source: &'a str, + lexer: Lexer<'a>, + token: Token, + token_span: Span, + + /// The current indentation level. + /// We allow it to be negative because in some cases we just want to decrease indentation + /// to preemptively cancel out an indentation that will come later which we don't want to take effect, + /// and we don't want to panic when reaching those negative values. + pub(crate) indentation: i32, + + /// When formatting chunks we sometimes need to remember the current indentation + /// and restore it later. This is what this stack is used for. + indentation_stack: Vec, + + /// Whenever a comment is written, this counter is incremented. + /// In this way we can know if comments were written while formatting some code: + /// we remember the previous value, format, then see if it increased. + /// This is used, for example, when transforming `foo::{bar}` into `foo::bar`: + /// we only do that if there were no comments between `{` and `}`. + written_comments_count: usize, + + /// If we find a comment like this one: + /// + /// // noir-fmt:ignore + /// + /// we won't format the next node (in some cases: only applies to statements and items). + ignore_next: bool, + + /// A counter to create GroupTags. + pub(crate) group_tag_counter: usize, + + /// We keep a copy of the config's max width because when we format chunk groups + /// we somethings change this so that a group has less space to write to. + pub(crate) max_width: usize, + + /// This is the buffer where we write the formatted code. + pub(crate) buffer: Buffer, +} + +impl<'a> Formatter<'a> { + pub(crate) fn new(source: &'a str, config: &'a Config) -> Self { + let lexer = Lexer::new(source).skip_comments(false).skip_whitespaces(false); + let mut formatter = Self { + config, + source, + lexer, + token: Token::EOF, + token_span: Default::default(), + indentation: 0, + indentation_stack: Vec::new(), + written_comments_count: 0, + ignore_next: false, + group_tag_counter: 0, + max_width: config.max_width, + buffer: Buffer::default(), + }; + formatter.bump(); + formatter + } + + pub(crate) fn format_program(&mut self, parsed_module: ParsedModule) { + self.skip_whitespace(); + self.skip_comments_and_whitespace_impl( + true, // write lines + true, // at beginning + ); + + self.format_parsed_module(parsed_module, self.ignore_next); + } + + pub(crate) fn format_parsed_module(&mut self, parsed_module: ParsedModule, ignore_next: bool) { + if !parsed_module.inner_doc_comments.is_empty() { + self.format_inner_doc_comments(); + } + + self.format_items(parsed_module.items, ignore_next); + self.write_line(); + } + + pub(crate) fn write_identifier(&mut self, ident: Ident) { + self.skip_comments_and_whitespace(); + + let Token::Ident(..) = self.token else { + panic!("Expected identifier, got {:?}", self.token); + }; + self.write(&ident.0.contents); + self.bump(); + } + + pub(crate) fn write_identifier_or_integer(&mut self, ident: Ident) { + self.skip_comments_and_whitespace(); + + if !matches!(self.token, Token::Ident(..) | Token::Int(..)) { + panic!("Expected identifier or integer, got {:?}", self.token); + } + self.write(&ident.0.contents); + self.bump(); + } + + pub(crate) fn write_left_paren(&mut self) { + self.write_token(Token::LeftParen); + } + + pub(crate) fn write_right_paren(&mut self) { + self.write_token(Token::RightParen); + } + + pub(crate) fn write_left_brace(&mut self) { + self.write_token(Token::LeftBrace); + } + + pub(crate) fn write_right_brace(&mut self) { + self.write_token(Token::RightBrace); + } + + pub(crate) fn write_left_bracket(&mut self) { + self.write_token(Token::LeftBracket); + } + + pub(crate) fn write_right_bracket(&mut self) { + self.write_token(Token::RightBracket); + } + + pub(crate) fn write_comma(&mut self) { + self.write_token(Token::Comma); + } + + pub(crate) fn write_semicolon(&mut self) { + self.write_token(Token::Semicolon); + } + + /// Writes the given keyword, if the current token is that keyword + /// (so this is a check that we are producing a token we expect to be in the source + /// we are traversing). Then advances to the next token. + /// + /// Calls `write_token` so comments and whitespaces are skipped before writing the keyword. + pub(crate) fn write_keyword(&mut self, keyword: Keyword) { + self.write_token(Token::Keyword(keyword)); + } + + /// Writes the given token, if the current token is the same as the given one + /// (so this is a check that we are producing a token we expect to be in the source + /// we are traversing). Then advances to the next token. + /// + /// Before writing the token any comments and spaces are skipped. This is so that + /// a caller can call `write_token`, `write_keyword`, `write_space`, etc., without + /// having to explicitly call `skip_comments_and_whitespace` in between those calls. + pub(crate) fn write_token(&mut self, token: Token) { + self.skip_comments_and_whitespace(); + if self.token == token { + self.write_current_token_and_bump(); + } else { + panic!("Expected token {:?}, got: {:?}", token, self.token); + } + } + + /// Writes the current token but doesn't advance to the next one. + pub(crate) fn write_current_token(&mut self) { + self.write(&self.token.to_string()); + } + + /// Writes the current token and advances to the next one + pub(crate) fn write_current_token_and_bump(&mut self) { + self.write(&self.token.to_string()); + self.bump(); + } + + /// Writes the current token trimming its end but doesn't advance to the next one. + /// Mainly used when writing comment lines, because we never want trailing spaces + /// inside comments. + pub(crate) fn write_current_token_trimming_end(&mut self) { + self.write(self.token.to_string().trim_end()); + } + + /// Writes the current token but without turning it into a string using `to_string()`. + /// Instead, we check the token's span and format what's in the original source there + /// (useful when formatting integer tokens, because a token like 0xFF ends up being an + /// integer with a value 255, but we don't want to change 0xFF to 255). + pub(crate) fn write_current_token_as_in_source(&mut self) { + self.write_source_span(self.token_span); + } + + /// Writes whatever is in the given span relative to the file's source that's being formatted. + pub(crate) fn write_source_span(&mut self, span: Span) { + self.write(&self.source[span.start() as usize..span.end() as usize]); + } + + /// Writes the current indentation to the buffer, but only if the buffer + /// is empty or it ends with a newline (otherwise we'd be indenting when not needed). + pub(crate) fn write_indentation(&mut self) { + if self.buffer.is_empty() || self.buffer.ends_with_newline() { + for _ in 0..self.indentation { + for _ in 0..self.config.tab_spaces { + self.write(" "); + } + } + } + } + + /// Writes whatever is in the source at the given span without formatting it, + /// then advances the lexer until past the end of the span. + /// This is mainly used to avoid formatting items and statements when a + /// `noir-fmt:ignore` comment is found. + pub(super) fn write_and_skip_span_without_formatting(&mut self, span: Span) { + self.write_source_span(span); + + while self.token_span.start() < span.end() && self.token != Token::EOF { + self.bump(); + } + } + + /// Advances the lexer until past the given span end without writing anything to the buffer. + pub(super) fn skip_past_span_end_without_formatting(&mut self, span_end: u32) { + while self.token_span.start() < span_end && self.token != Token::EOF { + self.bump(); + } + } + + /// Writes a string to the buffer. + pub(crate) fn write(&mut self, str: &str) { + self.buffer.write(str); + } + + pub(crate) fn current_line_width(&self) -> usize { + self.buffer.current_line_width() + } + + pub(crate) fn increase_indentation(&mut self) { + self.indentation += 1; + } + + pub(crate) fn decrease_indentation(&mut self) { + self.indentation -= 1; + } + + pub(crate) fn push_indentation(&mut self) { + self.indentation_stack.push(self.indentation); + } + + pub(crate) fn pop_indentation(&mut self) { + self.indentation = self.indentation_stack.pop().unwrap(); + } + + pub(crate) fn is_at_keyword(&self, keyword: Keyword) -> bool { + self.is_at(Token::Keyword(keyword)) + } + + pub(crate) fn is_at(&self, token: Token) -> bool { + self.token == token + } + + /// Advances to the next token (the current token is not written). + pub(crate) fn bump(&mut self) -> Token { + self.ignore_next = false; + + let next_token = self.read_token_internal(); + self.token_span = next_token.to_span(); + std::mem::replace(&mut self.token, next_token.into_token()) + } + + pub(crate) fn read_token_internal(&mut self) -> SpannedToken { + let token = self.lexer.next(); + if let Some(token) = token { + match token { + Ok(token) => token, + Err(err) => panic!("Expected lexer not to error, but got: {:?}", err), + } + } else { + SpannedToken::new(Token::EOF, Default::default()) + } + } +} diff --git a/tooling/nargo_fmt/src/formatter/alias.rs b/tooling/nargo_fmt/src/formatter/alias.rs new file mode 100644 index 00000000000..d4c63ebdd9e --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/alias.rs @@ -0,0 +1,41 @@ +use noirc_frontend::{ + ast::NoirTypeAlias, + token::{Keyword, Token}, +}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_type_alias(&mut self, type_alias: NoirTypeAlias) { + self.write_indentation(); + self.format_item_visibility(type_alias.visibility); + self.write_keyword(Keyword::Type); + self.write_space(); + self.write_identifier(type_alias.name); + self.format_generics(type_alias.generics); + self.write_space(); + self.write_token(Token::Assign); + self.write_space(); + self.format_type(type_alias.typ); + self.write_semicolon(); + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + #[test] + fn format_type_alias() { + let src = " pub type Foo = i32 ; "; + let expected = "pub type Foo = i32;\n"; + assert_format(src, expected); + } + + #[test] + fn format_generic_type_alias() { + let src = " pub type Foo < A, B > = i32 ; "; + let expected = "pub type Foo = i32;\n"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/attribute.rs b/tooling/nargo_fmt/src/formatter/attribute.rs new file mode 100644 index 00000000000..19d5730a546 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/attribute.rs @@ -0,0 +1,342 @@ +use noirc_frontend::token::{ + Attribute, Attributes, FunctionAttribute, MetaAttribute, SecondaryAttribute, TestScope, Token, +}; + +use crate::chunks::ChunkGroup; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_attributes(&mut self, attributes: Attributes) { + let mut all_attributes = Vec::new(); + for attribute in attributes.secondary { + all_attributes.push(Attribute::Secondary(attribute)); + } + if let Some((function_attribute, index)) = attributes.function { + all_attributes.insert(index, Attribute::Function(function_attribute)); + } + for attribute in all_attributes { + self.format_attribute(attribute); + } + } + + pub(super) fn format_secondary_attributes(&mut self, attributes: Vec) { + for attribute in attributes { + self.format_secondary_attribute(attribute); + } + } + + fn format_attribute(&mut self, attribute: Attribute) { + match attribute { + Attribute::Function(function_attribute) => { + self.format_function_attribute(function_attribute); + } + Attribute::Secondary(secondary_attribute) => { + self.format_secondary_attribute(secondary_attribute); + } + } + } + + fn format_function_attribute(&mut self, attribute: FunctionAttribute) { + self.skip_comments_and_whitespace(); + self.write_indentation(); + + if !matches!(self.token, Token::AttributeStart { .. }) { + panic!("Expected attribute start, got: {:?}", self.token); + } + + match attribute { + FunctionAttribute::Foreign(_) + | FunctionAttribute::Builtin(_) + | FunctionAttribute::Oracle(_) => self.format_one_arg_attribute(), + FunctionAttribute::Test(test_scope) => self.format_test_attribute(test_scope), + FunctionAttribute::Fold + | FunctionAttribute::NoPredicates + | FunctionAttribute::InlineAlways => self.format_no_args_attribute(), + } + + self.write_line(); + } + + pub(super) fn format_secondary_attribute(&mut self, attribute: SecondaryAttribute) { + self.skip_comments_and_whitespace(); + self.write_indentation(); + + if !matches!(self.token, Token::AttributeStart { .. }) { + panic!("Expected attribute start, got: {:?}", self.token); + } + + match attribute { + SecondaryAttribute::Deprecated(message) => { + self.format_deprecated_attribute(message); + } + SecondaryAttribute::ContractLibraryMethod + | SecondaryAttribute::Export + | SecondaryAttribute::Varargs + | SecondaryAttribute::UseCallersScope => { + self.format_no_args_attribute(); + } + SecondaryAttribute::Field(_) + | SecondaryAttribute::Abi(_) + | SecondaryAttribute::Allow(_) => { + self.format_one_arg_attribute(); + } + SecondaryAttribute::Tag(custom_attribute) => { + self.write_and_skip_span_without_formatting(custom_attribute.span); + } + SecondaryAttribute::Meta(meta_attribute) => { + self.format_meta_attribute(meta_attribute); + } + } + + self.write_line(); + } + + fn format_deprecated_attribute(&mut self, message: Option) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + if message.is_some() { + self.write_current_token_and_bump(); // deprecated + self.write_left_paren(); // ( + self.skip_comments_and_whitespace(); // message + self.write_current_token_and_bump(); // ) + self.write_right_paren(); + } else { + self.write_current_token_and_bump(); + } + self.write_right_bracket(); // ] + } + + fn format_test_attribute(&mut self, test_scope: TestScope) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // test + + match test_scope { + TestScope::None => (), + TestScope::ShouldFailWith { reason: None } => { + self.write_left_paren(); // ( + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // should_fail + self.write_right_paren(); // ) + } + TestScope::ShouldFailWith { reason: Some(..) } => { + self.write_left_paren(); // ( + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // should_fail_with + self.write_space(); + self.write_token(Token::Assign); + self.write_space(); + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // "reason" + self.write_right_paren(); // ) + } + } + + self.write_right_bracket(); // ] + } + + fn format_meta_attribute(&mut self, meta_attribute: MetaAttribute) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + self.format_path(meta_attribute.name); + self.skip_comments_and_whitespace(); + if self.is_at(Token::LeftParen) { + let comments_count_before_arguments = self.written_comments_count; + let has_arguments = !meta_attribute.arguments.is_empty(); + + let mut chunk_formatter = self.chunk_formatter(); + let mut group = ChunkGroup::new(); + group.text(chunk_formatter.chunk(|formatter| { + formatter.write_left_paren(); + })); + chunk_formatter.format_expressions_separated_by_comma( + meta_attribute.arguments, + false, // force trailing comma + &mut group, + ); + group.text(chunk_formatter.chunk(|formatter| { + formatter.write_right_paren(); + })); + if has_arguments || self.written_comments_count > comments_count_before_arguments { + self.format_chunk_group(group); + } + } + self.write_right_bracket(); + } + + fn format_no_args_attribute(&mut self) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // name + self.write_right_bracket(); // ] + } + + fn format_one_arg_attribute(&mut self) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // name + self.write_left_paren(); // ( + loop { + self.skip_comments_and_whitespace(); + if self.is_at(Token::RightParen) { + self.write_right_paren(); + break; + } else { + self.write_current_token_and_bump(); + } + } + self.write_right_bracket(); // ] + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + fn assert_format_attribute(src: &str, expected: &str) { + let src = format!(" {src} fn foo() {{}}"); + let expected = format!("{expected}\nfn foo() {{}}\n"); + assert_format(&src, &expected); + } + + #[test] + fn format_inner_tag_attribute() { + let src = " #!['foo] "; + let expected = "#!['foo]\n"; + assert_format(src, expected); + } + + #[test] + fn format_deprecated_attribute() { + let src = " #[ deprecated ] "; + let expected = "#[deprecated]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_deprecated_attribute_with_message() { + let src = " #[ deprecated ( \"use something else\" ) ] "; + let expected = "#[deprecated(\"use something else\")]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_contract_library_method() { + let src = " #[ contract_library_method ] "; + let expected = "#[contract_library_method]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_export() { + let src = " #[ export ] "; + let expected = "#[export]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_varargs() { + let src = " #[ varargs ] "; + let expected = "#[varargs]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_use_callers_scope() { + let src = " #[ use_callers_scope ] "; + let expected = "#[use_callers_scope]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_field_attribute() { + let src = " #[ field ( bn256 ) ] "; + let expected = "#[field(bn256)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_abi_attribute() { + let src = " #[ abi ( foo ) ] "; + let expected = "#[abi(foo)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_allow_attribute() { + let src = " #[ allow ( unused_vars ) ] "; + let expected = "#[allow(unused_vars)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_meta_attribute_without_arguments() { + let src = " #[ custom ] "; + let expected = "#[custom]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_meta_attribute_without_arguments_removes_parentheses() { + let src = " #[ custom ( ) ] "; + let expected = "#[custom]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_meta_attribute_without_arguments_but_comment() { + let src = " #[ custom ( /* nothing */ ) ] "; + let expected = "#[custom( /* nothing */ )]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_meta_attribute_with_arguments() { + let src = " #[ custom ( 1 , 2, [ 3, 4 ], ) ] "; + let expected = "#[custom(1, 2, [3, 4])]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_foreign_attribute() { + let src = " #[ foreign ( foo ) ] "; + let expected = "#[foreign(foo)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_recursive_attribute() { + let src = " #[ recursive ] "; + let expected = "#[recursive]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_test_attribute() { + let src = " #[ test ] "; + let expected = "#[test]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_test_should_fail_attribute() { + let src = " #[ test ( should_fail )] "; + let expected = "#[test(should_fail)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_test_should_fail_with_reason_attribute() { + let src = " #[ test ( should_fail_with=\"reason\" )] "; + let expected = "#[test(should_fail_with = \"reason\")]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_multiple_function_attributes() { + let src = " #[foo] #[test] #[bar] "; + let expected = "#[foo]\n#[test]\n#[bar]"; + assert_format_attribute(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/buffer.rs b/tooling/nargo_fmt/src/formatter/buffer.rs new file mode 100644 index 00000000000..3e4bebef608 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/buffer.rs @@ -0,0 +1,66 @@ +/// A buffer to write to. +/// It keeps track of the current line width and provides a few useful methods +/// to deal with the buffer contents. +#[derive(Default, Debug)] +pub(crate) struct Buffer { + buffer: String, + + /// How many characters we've written so far in the current line + /// (useful to avoid exceeding the configurable maximum) + current_line_width: usize, +} + +impl Buffer { + pub(crate) fn is_empty(&self) -> bool { + self.buffer.is_empty() + } + + pub(crate) fn ends_with_newline(&self) -> bool { + self.buffer.ends_with('\n') + } + + pub(crate) fn ends_with_double_newline(&self) -> bool { + self.buffer.ends_with("\n\n") + } + + pub(crate) fn ends_with_space(&self) -> bool { + self.buffer.ends_with(' ') + } + + pub(crate) fn write(&mut self, str: &str) { + self.buffer.push_str(str); + + if str.ends_with('\n') { + self.current_line_width = 0; + } else { + self.current_line_width += str.chars().count(); + } + } + + /// Trim spaces from the end of the buffer. + pub(crate) fn trim_spaces(&mut self) { + while self.buffer.ends_with(' ') { + self.buffer.truncate(self.buffer.len() - 1); + self.current_line_width -= 1; + } + } + + /// Trim commas from the end of the buffer. Returns true if a comma was trimmed. + pub(super) fn trim_comma(&mut self) -> bool { + if self.buffer.ends_with(',') { + self.buffer.truncate(self.buffer.len() - 1); + self.current_line_width -= 1; + true + } else { + false + } + } + + pub(crate) fn contents(self) -> String { + self.buffer + } + + pub(crate) fn current_line_width(&self) -> usize { + self.current_line_width + } +} diff --git a/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs b/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs new file mode 100644 index 00000000000..e20eb4291d1 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs @@ -0,0 +1,861 @@ +use noirc_frontend::token::Token; + +use super::Formatter; + +#[cfg(windows)] +const NEWLINE: &str = "\r\n"; +#[cfg(not(windows))] +const NEWLINE: &str = "\n"; + +impl<'a> Formatter<'a> { + /// Writes a single space, skipping any whitespace and comments. + /// That is, suppose the next token is a big whitespace, possibly with multiple lines. + /// Those are skipped but only one space is written. In this way if we have + /// "mod foo" it's transformed to "mod foo". + /// If there are comments in between `mod` and `foo` they are written, though! + /// No comment is ever lost. + /// + /// A space is not appended to the buffer is it already ends with a space. + pub(crate) fn write_space(&mut self) { + self.skip_comments_and_whitespace(); + self.write_space_without_skipping_whitespace_and_comments(); + } + + /// Writes a single space, but doesn't skip whitespace and comments before doing that. + /// + /// A space is not appended to the buffer is it already ends with a space. + pub(crate) fn write_space_without_skipping_whitespace_and_comments(&mut self) { + if !self.buffer.ends_with_newline() && !self.buffer.ends_with_space() { + self.write(" "); + } + } + + pub(crate) fn skip_whitespace(&mut self) { + while let Token::Whitespace(..) = &self.token { + self.bump(); + } + } + + /// Only skips whitespace if it doesn't have newlines in it. + /// Note that this doesn't write whitespace or comments at all. + pub(crate) fn skip_whitespace_if_it_is_not_a_newline(&mut self) { + while let Token::Whitespace(whitespace) = &self.token { + if whitespace.contains('\n') { + break; + } + self.bump(); + } + } + + /// Skips comments and whitespace, writing newlines if there are any. + /// If there are multiple consecutive newlines, only one is written. + pub(crate) fn skip_comments_and_whitespace(&mut self) { + self.skip_comments_and_whitespace_impl( + false, // write multiple lines + false, // at beginning + ); + } + + /// Similar to skip_comments_and_whitespace, but will write two lines if + /// multiple newlines are found (but at most two lines at a time). + pub(crate) fn skip_comments_and_whitespace_writing_multiple_lines_if_found(&mut self) { + self.skip_comments_and_whitespace_impl( + true, // write multiple lines + false, // at beginning + ); + } + + pub(crate) fn skip_comments_and_whitespace_impl( + &mut self, + write_multiple_lines: bool, + at_beginning: bool, + ) { + // Number of newlines we just skipped. + let mut number_of_newlines = 0; + + // Did we just passed some whitespace? + let mut passed_whitespace = false; + + // Was the last token we processed a block comment? + let mut last_was_block_comment = false; + + let mut ignore_next = false; + + loop { + match &self.token { + Token::Whitespace(whitespace) => { + number_of_newlines = whitespace.chars().filter(|char| *char == '\n').count(); + passed_whitespace = whitespace.ends_with(' '); + + if last_was_block_comment && number_of_newlines > 0 { + if number_of_newlines > 1 { + self.write_multiple_lines_without_skipping_whitespace_and_comments(); + } else { + self.write_line_without_skipping_whitespace_and_comments(); + } + + self.bump(); + + // Only indent for what's coming next if it's a comment + // (otherwise a closing brace must come and we wouldn't want to indent that) + if matches!( + &self.token, + Token::LineComment(_, None) | Token::BlockComment(_, None), + ) { + self.write_indentation(); + } + + number_of_newlines = 0; + passed_whitespace = false; + } else { + self.bump(); + } + + last_was_block_comment = false; + } + Token::LineComment(comment, None) => { + if comment.trim() == "noir-fmt:ignore" { + ignore_next = true; + } + + // Here we check if we need to write one line, two lines or none after the + // end of the line comment. + if number_of_newlines > 1 && write_multiple_lines { + self.write_multiple_lines_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else if number_of_newlines > 0 { + self.write_line_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else if !(at_beginning && self.buffer.is_empty()) { + // We write a space before a line comment so if you have code like this: + // "1// comment" it's transformed to "1 // comment". + // What if there was already a space? It's all good, `write_space` + // will never write two consecutive spaces. + self.write_space_without_skipping_whitespace_and_comments(); + } + + self.write_current_token_trimming_end(); + self.write_line_without_skipping_whitespace_and_comments(); + number_of_newlines = 1; + self.bump(); + passed_whitespace = false; + last_was_block_comment = false; + self.written_comments_count += 1; + } + Token::BlockComment(comment, None) => { + if comment.trim() == "noir-fmt:ignore" { + ignore_next = true; + } + + // Here we check if we need to write one line, two lines or none after the + // end of the block comment. + if number_of_newlines > 1 && write_multiple_lines { + self.write_multiple_lines_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else if number_of_newlines > 0 { + self.write_line_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else if passed_whitespace { + // We write a space before a line comment so if you have code like this: + // "1/* comment */" it's transformed to "1 /* comment */". + // What if there was already a space? It's all good, `write_space` + // will never write two consecutive spaces. + self.write_space_without_skipping_whitespace_and_comments(); + } + self.write_current_token_and_bump(); + passed_whitespace = false; + last_was_block_comment = true; + self.written_comments_count += 1; + } + _ => break, + } + } + + // Case when we passed some whitespace with newlines but no comments followed it. + if number_of_newlines > 1 && write_multiple_lines { + self.write_multiple_lines_without_skipping_whitespace_and_comments(); + } + + self.ignore_next = ignore_next; + } + + /// Returns the number of newlines that come next, if we are at a whitespace + /// token (otherwise returns 0). + pub(crate) fn following_newlines_count(&self) -> usize { + let Token::Whitespace(whitespace) = &self.token else { + return 0; + }; + + whitespace.chars().filter(|char| *char == '\n').count() + } + + /// Writes a single newline, if the last thing we wrote wasn't also a newline + /// (this prevents multiple consecutive newlines, though that's still possible to + /// do if you call `write_multiple_lines_...`). + /// + /// Any whitespace or comments found right at and after the current token are "skipped" + /// (whitespace is discarded, comments are written). + pub(crate) fn write_line(&mut self) { + self.skip_comments_and_whitespace_impl( + true, // writing newline + false, // at beginning + ); + self.write_line_without_skipping_whitespace_and_comments(); + } + + pub(crate) fn write_line_without_skipping_whitespace_and_comments(&mut self) -> bool { + if !self.buffer.ends_with_newline() && !self.buffer.ends_with_space() { + self.write(NEWLINE); + true + } else { + false + } + } + + // Modifies the current buffer so that it will always have two newlines at the end. + pub(crate) fn write_multiple_lines_without_skipping_whitespace_and_comments(&mut self) { + if self.buffer.ends_with_double_newline() { + // Nothing + } else if self.buffer.ends_with_newline() { + self.write(NEWLINE); + } else { + self.write(NEWLINE); + self.write(NEWLINE); + } + } + + /// Trim spaces from the end of the buffer. + pub(crate) fn trim_spaces(&mut self) { + self.buffer.trim_spaces(); + } + + /// Trim commas from the end of the buffer. Returns true if a comma was trimmed. + pub(crate) fn trim_comma(&mut self) -> bool { + self.buffer.trim_comma() + } +} + +#[cfg(test)] +mod tests { + use crate::{assert_format, assert_format_with_max_width}; + + #[test] + fn format_array_in_global_with_line_comments() { + let src = "global x = [ // hello + 1 , 2 ] ;"; + let expected = "global x = [ + // hello + 1, 2, +]; +"; + assert_format(src, expected); + } + + #[test] + fn format_array_in_global_with_line_comments_2() { + let src = "global x = [ // hello + [ 1 , 2 ] ] ;"; + let expected = "global x = [ + // hello + [1, 2], +]; +"; + assert_format(src, expected); + } + + #[test] + fn format_array_in_global_with_line_comments_3() { + let src = "global x = + [ + // hello + [1, 2], + ]; +"; + let expected = "global x = [ + // hello + [1, 2], +]; +"; + assert_format(src, expected); + } + + #[test] + fn format_array_in_global_with_line_comments_4() { + let src = "global x = + [ + 1, // world + 2, 3, + ]; +"; + let expected = "global x = [ + 1, // world + 2, 3, +]; +"; + assert_format(src, expected); + } + + #[test] + fn format_array_in_global_with_block_comments() { + let src = "global x = [ /* hello */ + 1 , 2 ] ;"; + let expected = "global x = [ + /* hello */ 1, + 2, +]; +"; + assert_format_with_max_width(src, expected, 20); + } + + #[test] + fn format_if_with_comment_after_condition() { + let src = "global x = if 123 // some comment + { 456 } ;"; + let expected = "global x = if 123 // some comment +{ + 456 +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_if_with_comment_after_else() { + let src = "global x = if 123 { 456 } else // some comment + { 789 };"; + let expected = "global x = if 123 { + 456 +} else // some comment +{ + 789 +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_function_when_some_args_are_multiline_because_of_line_comments() { + let src = "fn foo ( a: i32, // comment + b: i32 + ) { } "; + let expected = "fn foo( + a: i32, // comment + b: i32, +) {} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_when_some_args_are_multiline_because_of_line_comments_2() { + let src = "fn foo ( a: i32, // comment + // another + b: i32 // another comment + ) { } "; + let expected = "fn foo( + a: i32, // comment + // another + b: i32, // another comment +) {} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_when_some_args_are_multiline_because_of_block_comments() { + let src = "fn foo ( a: i32 /* + some + comment */, b: i32 + ) { } "; + let expected = "fn foo( + a: i32 /* + some + comment */, + b: i32, +) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_comment_after_parameters() { + let src = "fn main() + // hello + {}"; + let expected = "fn main() +// hello +{} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_line_comment_in_parameters() { + let src = "fn main( + // hello + ) + {}"; + let expected = "fn main( + // hello +) {} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_line_comment_on_top_of_parameter() { + let src = "fn main( +// hello +unit: () +) {}"; + let expected = "fn main( + // hello + unit: (), +) {} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_block_comment_in_params() { + let src = "fn main(/* test */) {}"; + let expected = "fn main(/* test */) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_body_and_block_comment() { + let src = "fn main() { + /* foo */ + 1 }"; + let expected = "fn main() { + /* foo */ + 1 +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_body_one_expr_trailing_comment() { + let src = "mod moo { fn main() { 1 // yes + } }"; + let expected = "mod moo { + fn main() { + 1 // yes + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_body_one_expr_semicolon_trailing_comment() { + let src = "mod moo { fn main() { 1 ; // yes + } }"; + let expected = "mod moo { + fn main() { + 1; // yes + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_many_exprs_trailing_comments() { + let src = "mod moo { fn main() { 1 ; // yes + 2 ; // no + 3 // maybe + } }"; + let expected = "mod moo { + fn main() { + 1; // yes + 2; // no + 3 // maybe + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_block_comment_after_two_newlines() { + let src = "fn foo() { + 1; + + /* world */ + 2 +} +"; + let expected = "fn foo() { + 1; + + /* world */ + 2 +} +"; + assert_format(src, expected); + } + + #[test] + fn format_comment_on_top_of_let_followed_by_statement() { + let src = "fn foo() { + 1; + + // Comment + let x = 1; +} +"; + let expected = "fn foo() { + 1; + + // Comment + let x = 1; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_module_declaration_with_block_comments() { + let src = " mod/*a*/ foo /*b*/ ; "; + let expected = "mod/*a*/ foo /*b*/;\n"; + assert_format(src, expected); + } + + #[test] + fn format_module_declaration_with_inline_comments() { + let src = " mod // a + foo // b + ; "; + let expected = "mod // a +foo // b +; +"; + assert_format(src, expected); + } + + #[test] + fn format_submodule_with_line_comments_in_separate_line() { + let src = " #[foo] pub mod foo { +// one +#[hello] +mod bar; +// two +}"; + let expected = "#[foo] +pub mod foo { + // one + #[hello] + mod bar; + // two +} +"; + assert_format(src, expected); + } + + #[test] + fn format_submodule_with_line_comment_in_same_line() { + let src = " #[foo] pub mod foo { // one +mod bar; +}"; + let expected = "#[foo] +pub mod foo { // one + mod bar; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_submodule_with_block_comment() { + let src = " #[foo] pub mod foo { /* one */ +/* two */ +mod bar; +}"; + let expected = "#[foo] +pub mod foo { /* one */ + /* two */ + mod bar; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_submodule_with_block_comment_2() { + let src = "mod foo { + /* one */ +}"; + let expected = "mod foo { + /* one */ +} +"; + assert_format(src, expected); + } + + #[test] + fn keeps_spaces_between_comments() { + let src = " mod foo { + +// hello + +// world + +} "; + let expected = "mod foo { + + // hello + + // world + +} +"; + assert_format(src, expected); + } + + #[test] + fn comment_with_leading_space() { + let src = " // comment + // hello +mod foo ; "; + let expected = "// comment +// hello +mod foo; +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_block_statement_with_inline_block_comment() { + let src = " fn foo() { { /* hello */ } } "; + let expected = "fn foo() { + { /* hello */ } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_struct_with_block_comments() { + let src = " struct Foo { + /* hello */ + } + "; + let expected = "struct Foo { + /* hello */ +} +"; + assert_format(src, expected); + } + + #[test] + fn format_struct_with_just_comments() { + let src = " mod foo { struct Foo { +// hello + } } + "; + let expected = "mod foo { + struct Foo { + // hello + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_block_comment_no_whitespace_in_block_single_line() { + let src = "global x = {/*foo*/};"; + let expected = "global x = { /*foo*/ };\n"; + assert_format(src, expected); + } + + #[test] + fn format_block_comment_no_whitespace_but_newline_in_block_single_line() { + let src = "global x = {/*foo*/ + };"; + let expected = "global x = { /*foo*/ };\n"; + assert_format(src, expected); + } + + #[test] + fn format_line_comment_in_block_same_line() { + let src = "global x = { // foo + };"; + let expected = "global x = { // foo +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_line_comment_in_block_separate_line() { + let src = "global x = { + // foo + };"; + let expected = "global x = { + // foo +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_block_comment_in_parenthesized_expression() { + let src = "global x = ( /* foo */ 1 );"; + let expected = "global x = ( /* foo */ 1);\n"; + assert_format(src, expected); + } + + #[test] + fn format_line_comment_in_parenthesized() { + let src = "global x = ( // hello + 1 );"; + let expected = "global x = ( + // hello + 1 +);\n"; + assert_format(src, expected); + } + + #[test] + fn format_index_with_comment() { + let src = "global x = foo[// hello + 1];"; + let expected = "global x = foo[ + // hello + 1 +];\n"; + assert_format(src, expected); + } + + #[test] + fn format_comment_in_infix_between_lhs_and_operator() { + let src = "global x = 1/* comment */+ 2 ;"; + let expected = "global x = 1 /* comment */ + 2;\n"; + assert_format(src, expected); + } + + #[test] + fn format_comment_in_constructor_inside_function() { + let src = "fn foo() { MyStruct {/*test*/}; } "; + let expected = "fn foo() { + MyStruct { /*test*/ }; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_block_comment_before_constructor_field() { + let src = "global x = Foo {/*comment*/field}; "; + let expected = "global x = Foo { /*comment*/ field };\n"; + assert_format(src, expected); + } + + #[test] + fn format_line_comment_before_constructor_field() { + let src = "global x = Foo { // foo + field}; "; + let expected = "global x = Foo { + // foo + field, +};\n"; + assert_format(src, expected); + } + + #[test] + fn format_comment_in_empty_constructor() { + let src = "global x = Foo { // comment + }; "; + let expected = "global x = Foo { // comment +};\n"; + assert_format(src, expected); + } + + #[test] + fn format_comment_after_parenthesized() { + let src = "global x = ( + 1 + // hello + ) + ; "; + let expected = "global x = ( + 1 + // hello +);\n"; + assert_format(src, expected); + } + + #[test] + fn format_comment_in_single_element_tuple() { + let src = "global x = ( 1 /* hello */ , );"; + let expected = "global x = (1 /* hello */,);\n"; + assert_format(src, expected); + } + + #[test] + fn format_comment_after_impl_function() { + let src = "impl Foo { fn foo() {} + // bar + }"; + let expected = "impl Foo { + fn foo() {} + // bar +} +"; + assert_format(src, expected); + } + + #[test] + fn format_comment_after_trait_impl_function() { + let src = "impl Foo for Bar { fn foo() {} + // bar + }"; + let expected = "impl Foo for Bar { + fn foo() {} + // bar +} +"; + assert_format(src, expected); + } + + #[test] + fn format_comment_after_trait_function() { + let src = "trait Foo { fn foo() {} + // bar + }"; + let expected = "trait Foo { + fn foo() {} + // bar +} +"; + assert_format(src, expected); + } + + #[test] + fn keeps_newlines_after_comment_at_the_beginning() { + let src = "// foo + +global x = 1; +"; + let expected = src; + assert_format(src, expected); + } + + #[test] + fn keeps_newlines_after_comment_at_the_beginning_2() { + let src = " + + // foo + +global x = 1; +"; + let expected = "// foo + +global x = 1; +"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/doc_comments.rs b/tooling/nargo_fmt/src/formatter/doc_comments.rs new file mode 100644 index 00000000000..ac2cae10c78 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/doc_comments.rs @@ -0,0 +1,72 @@ +use noirc_frontend::token::{DocStyle, Token}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_inner_doc_comments(&mut self) { + loop { + self.skip_comments_and_whitespace(); + + match self.token { + Token::LineComment(_, Some(DocStyle::Inner)) + | Token::BlockComment(_, Some(DocStyle::Inner)) => { + self.write_indentation(); + self.write_current_token_trimming_end(); + self.bump(); + self.write_line(); + } + _ => break, + } + } + } + + pub(super) fn format_outer_doc_comments(&mut self) { + loop { + self.skip_comments_and_whitespace(); + + match self.token { + Token::LineComment(_, Some(DocStyle::Outer)) + | Token::BlockComment(_, Some(DocStyle::Outer)) => { + self.write_indentation(); + self.write_current_token_trimming_end(); + self.bump(); + self.write_line(); + } + _ => break, + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + #[test] + fn format_inner_doc_comments() { + let src = " #![hello] #![world]"; + let expected = "#![hello]\n#![world]\n"; + assert_format(src, expected); + } + + #[test] + fn format_inner_doc_comments_with_line_comments() { + let src = " #![hello] // foo + // bar + #![world]"; + let expected = "#![hello] // foo +// bar +#![world] +"; + assert_format(src, expected); + } + + #[test] + fn format_inner_doc_comments_with_block_comments() { + let src = " #![hello] /* foo */ #![world]"; + let expected = "#![hello] /* foo */ +#![world] +"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/expression.rs b/tooling/nargo_fmt/src/formatter/expression.rs new file mode 100644 index 00000000000..ef04276a605 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/expression.rs @@ -0,0 +1,2329 @@ +use noirc_frontend::{ + ast::{ + ArrayLiteral, BinaryOpKind, BlockExpression, CallExpression, CastExpression, + ConstructorExpression, Expression, ExpressionKind, IfExpression, IndexExpression, + InfixExpression, Lambda, Literal, MemberAccessExpression, MethodCallExpression, + PrefixExpression, TypePath, UnaryOp, UnresolvedTypeData, + }, + token::{Keyword, Token}, +}; + +use crate::chunks::{Chunk, ChunkFormatter, ChunkGroup, GroupKind, GroupTag, TextChunk}; + +use super::Formatter; + +#[derive(Debug)] +struct FormattedLambda { + group: ChunkGroup, + first_line_width: usize, +} + +impl<'a, 'b> ChunkFormatter<'a, 'b> { + pub(super) fn format_expression(&mut self, expression: Expression, group: &mut ChunkGroup) { + group.leading_comment(self.skip_comments_and_whitespace_chunk()); + + match expression.kind { + ExpressionKind::Literal(literal) => self.format_literal(literal, group), + ExpressionKind::Block(block) => { + group.group(self.format_block_expression( + block, false, // force multiple lines + )); + } + ExpressionKind::Prefix(prefix_expression) => { + group.group(self.format_prefix(*prefix_expression)); + } + ExpressionKind::Index(index_expression) => { + group.group(self.format_index_expression(*index_expression)); + } + ExpressionKind::Call(call) => group.group(self.format_call(*call)), + ExpressionKind::MethodCall(method_call) => { + group.group(self.format_method_call(*method_call)); + } + ExpressionKind::Constructor(constructor) => { + group.group(self.format_constructor(*constructor)); + } + ExpressionKind::MemberAccess(member_access) => { + group.group(self.format_member_access(*member_access)); + } + ExpressionKind::Cast(cast_expression) => { + group.group(self.format_cast(*cast_expression)); + } + ExpressionKind::Infix(infix_expression) => { + group.group(self.format_infix_expression(*infix_expression)); + } + ExpressionKind::If(if_expression) => { + group.group(self.format_if_expression( + *if_expression, + false, // force multiple lines + )); + } + ExpressionKind::Variable(path) => { + group.text(self.chunk(|formatter| { + formatter.format_path(path); + })); + } + ExpressionKind::Tuple(exprs) => group.group(self.format_tuple(exprs)), + ExpressionKind::Lambda(lambda) => group.group(self.format_lambda(*lambda).group), + ExpressionKind::Parenthesized(expression) => { + group.group(self.format_parenthesized_expression(*expression)); + } + ExpressionKind::Quote(..) => { + group.group(self.format_quote()); + } + ExpressionKind::Unquote(..) => { + unreachable!("Should not be present in the AST") + } + ExpressionKind::Comptime(block_expression, _span) => { + group.group(self.format_comptime_expression( + block_expression, + false, // force multiple lines + )); + } + ExpressionKind::Unsafe(block_expression, _span) => { + group.group(self.format_unsafe_expression( + block_expression, + false, // force multiple lines + )); + } + ExpressionKind::AsTraitPath(as_trait_path) => { + group.text(self.chunk(|formatter| formatter.format_as_trait_path(as_trait_path))); + } + ExpressionKind::TypePath(type_path) => { + group.group(self.format_type_path(type_path)); + } + ExpressionKind::Resolved(..) + | ExpressionKind::Interned(..) + | ExpressionKind::InternedStatement(..) + | ExpressionKind::Error => unreachable!("Should not be present in the AST"), + } + } + + fn format_literal(&mut self, literal: Literal, group: &mut ChunkGroup) { + match literal { + Literal::Unit => group.text(self.chunk(|formatter| { + formatter.write_left_paren(); + formatter.write_right_paren(); + })), + Literal::Bool(_) | Literal::Str(_) | Literal::FmtStr(_, _) | Literal::RawStr(..) => { + group.text(self.chunk(|formatter| { + formatter.write_current_token_as_in_source(); + formatter.bump(); + })); + } + Literal::Integer(..) => group.text(self.chunk(|formatter| { + if formatter.is_at(Token::Minus) { + formatter.write_token(Token::Minus); + formatter.skip_comments_and_whitespace(); + } + formatter.write_current_token_as_in_source(); + formatter.bump(); + })), + Literal::Array(array_literal) => group.group(self.format_array_literal( + array_literal, + false, // is slice + )), + Literal::Slice(array_literal) => { + group.group(self.format_array_literal( + array_literal, + true, // is slice + )); + } + } + } + + fn format_array_literal(&mut self, literal: ArrayLiteral, is_slice: bool) -> ChunkGroup { + let mut group = ChunkGroup::new(); + + group.text(self.chunk(|formatter| { + if is_slice { + formatter.write_token(Token::Ampersand); + } + formatter.write_left_bracket(); + })); + + match literal { + ArrayLiteral::Standard(exprs) => { + group.kind = GroupKind::ExpressionList { + prefix_width: group.width(), + expressions_count: exprs.len(), + }; + + let maximum_element_width = self.format_expressions_separated_by_comma( + exprs, false, // force trailing comma + &mut group, + ); + group.one_chunk_per_line = + maximum_element_width > self.config.short_array_element_width_threshold; + } + ArrayLiteral::Repeated { repeated_element, length } => { + group.increase_indentation(); + group.line(); + + self.format_expression(*repeated_element, &mut group); + group.semicolon(self); + group.space(self); + self.format_expression(*length, &mut group); + + group.decrease_indentation(); + group.line(); + } + } + + group.text(self.chunk(|formatter| formatter.write_right_bracket())); + + group + } + + fn format_tuple(&mut self, exprs: Vec) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.one_chunk_per_line = false; + + let force_trailing_comma = exprs.len() == 1; + + group.text(self.chunk(|formatter| { + formatter.write_left_paren(); + })); + + group.kind = GroupKind::ExpressionList { + prefix_width: group.width(), + expressions_count: exprs.len(), + }; + + self.format_expressions_separated_by_comma(exprs, force_trailing_comma, &mut group); + + group.text(self.chunk(|formatter| formatter.write_right_paren())); + + group + } + + fn format_lambda(&mut self, lambda: Lambda) -> FormattedLambda { + let mut group = ChunkGroup::new(); + + let lambda_has_return_type = lambda.return_type.typ != UnresolvedTypeData::Unspecified; + + let params_and_return_type_chunk = self.chunk(|formatter| { + formatter.write_token(Token::Pipe); + for (index, (pattern, typ)) in lambda.parameters.into_iter().enumerate() { + if index > 0 { + formatter.write_comma(); + formatter.write_space(); + } + formatter.format_pattern(pattern); + if typ.typ != UnresolvedTypeData::Unspecified { + formatter.write_token(Token::Colon); + formatter.write_space(); + formatter.format_type(typ); + } + } + formatter.skip_comments_and_whitespace(); + if formatter.is_at(Token::Comma) { + formatter.bump(); + } + formatter.write_token(Token::Pipe); + formatter.write_space(); + if lambda_has_return_type { + formatter.write_token(Token::Arrow); + formatter.write_space(); + formatter.format_type(lambda.return_type); + formatter.write_space(); + } + }); + + let params_and_return_type_chunk_width = params_and_return_type_chunk.width; + + group.text(params_and_return_type_chunk); + + let block_statement_count = if let ExpressionKind::Block(block) = &lambda.body.kind { + Some(block.statements.len()) + } else { + None + }; + + let mut body_group = ChunkGroup::new(); + + let comments_count_before_body = self.written_comments_count; + self.format_expression(lambda.body, &mut body_group); + + body_group.kind = GroupKind::LambdaBody { + block_statement_count, + has_comments: self.written_comments_count > comments_count_before_body, + lambda_has_return_type, + }; + + group.group(body_group); + + let first_line_width = params_and_return_type_chunk_width + + (if block_statement_count.is_some() { + // 1 because we already have `|param1, param2, ..., paramN| ` (including the space) + // so all that's left is a `{`. + 1 + } else { + // The body is not a block so we can write it right away + 0 + }); + + FormattedLambda { group, first_line_width } + } + + fn format_parenthesized_expression(&mut self, expr: Expression) -> ChunkGroup { + let is_nested_parenthesized = matches!(expr.kind, ExpressionKind::Parenthesized(..)); + + let mut group = ChunkGroup::new(); + let left_paren_chunk = self.chunk(|formatter| { + formatter.write_left_paren(); + }); + + let mut expr_group = ChunkGroup::new(); + let mut has_comments = false; + + let comment_after_left_paren_chunk = self.skip_comments_and_whitespace_chunk(); + if !comment_after_left_paren_chunk.string.trim().is_empty() { + has_comments = true; + } + + expr_group.leading_comment(comment_after_left_paren_chunk); + + self.format_expression(expr, &mut expr_group); + + let comment_before_right_parent_chunk = self.skip_comments_and_whitespace_chunk(); + if !comment_before_right_parent_chunk.string.trim().is_empty() { + has_comments = true; + } + + let right_paren_chunk = self.chunk(|formatter| { + formatter.write_right_paren(); + }); + + if is_nested_parenthesized && !has_comments && self.config.remove_nested_parens { + group.chunks.extend(expr_group.chunks); + } else { + group.text(left_paren_chunk); + group.increase_indentation(); + group.line(); + group.chunks.extend(expr_group.chunks); + group.text(comment_before_right_parent_chunk); + group.decrease_indentation(); + group.line(); + group.text(right_paren_chunk); + } + + group + } + + pub(super) fn format_quote(&mut self) -> ChunkGroup { + // A quote's prefix isn't captured in the token, so let's figure it out which one + // is it by looking at the source code. + let mut quote_source_code = + &self.source[self.token_span.start() as usize..self.token_span.end() as usize]; + + // Remove "quote" and any whitespace following it + quote_source_code = quote_source_code.strip_prefix("quote").unwrap(); + quote_source_code = quote_source_code.trim_start(); + + // The first char is the delimiter + let delimiter_start = quote_source_code.chars().next().unwrap(); + let delimiter_end = match delimiter_start { + '(' => ')', + '{' => '}', + '[' => ']', + _ => panic!("Unexpected delimiter: {}", delimiter_start), + }; + + // We use the current token rather than the Tokens we got from `Token::Quote` because + // the current token has whitespace and comments in it, while the one we got from + // the parser doesn't. + let Token::Quote(tokens) = self.bump() else { + panic!("Expected current token to be Quote"); + }; + + let mut group = ChunkGroup::new(); + group.verbatim(self.chunk(|formatter| { + formatter.write("quote"); + formatter.write_space(); + formatter.write(&delimiter_start.to_string()); + for token in tokens.0 { + formatter.write_source_span(token.to_span()); + } + formatter.write(&delimiter_end.to_string()); + })); + group + } + + pub(super) fn format_comptime_expression( + &mut self, + block: BlockExpression, + force_multiple_lines: bool, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.text(self.chunk(|formatter| { + formatter.write_keyword(Keyword::Comptime); + formatter.write_space(); + })); + group.group(self.format_block_expression(block, force_multiple_lines)); + group + } + + pub(super) fn format_unsafe_expression( + &mut self, + block: BlockExpression, + force_multiple_lines: bool, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.text(self.chunk(|formatter| { + formatter.format_outer_doc_comments(); + formatter.write_keyword(Keyword::Unsafe); + formatter.write_space(); + })); + group.group(self.format_block_expression(block, force_multiple_lines)); + group + } + + pub(super) fn format_type_path(&mut self, type_path: TypePath) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.text(self.chunk(|formatter| { + formatter.format_type(type_path.typ); + formatter.write_token(Token::DoubleColon); + formatter.write_identifier(type_path.item); + if let Some(turbofish) = type_path.turbofish { + formatter.write_token(Token::DoubleColon); + formatter.format_generic_type_args(turbofish); + } + })); + group + } + + /// Returns the maximum width of each expression to format. For example, + /// if the list is [1, 234, 56], the maximum width is 3 (that of `234`). + pub(super) fn format_expressions_separated_by_comma( + &mut self, + exprs: Vec, + force_trailing_comma: bool, + group: &mut ChunkGroup, + ) -> usize { + if exprs.is_empty() { + if let Some(inner_group) = self.empty_block_contents_chunk() { + group.group(inner_group); + } + 0 + } else { + let exprs_len = exprs.len(); + let mut expr_index = 0; + let mut max_width = 0; + + self.format_items_separated_by_comma( + exprs, + force_trailing_comma, + false, // surround with spaces + group, + |formatter, expr, chunks| { + // If the last expression in the list is a lambda, we format it but we mark + // the chunk in a special way: it likely has newlines, but we don't want + // those newlines to affect the parent group. For example: + // + // foo(1, 2, |x| { + // let y = x + 1; + // y * 2 + // }) + if expr_index == exprs_len - 1 { + if let ExpressionKind::Lambda(lambda) = expr.kind { + let mut lambda_group = formatter.format_lambda(*lambda); + lambda_group.group.kind = GroupKind::LambdaAsLastExpressionInList { + first_line_width: lambda_group.first_line_width, + indentation: None, + }; + chunks.group(lambda_group.group); + return; + } + } + expr_index += 1; + + let chunks_len_before_expression = chunks.chunks.len(); + + formatter.format_expression(expr, chunks); + + let chunks_len_after_expression = chunks.chunks.len(); + let expression_width: usize = (chunks_len_before_expression + ..chunks_len_after_expression) + .map(|index| chunks.chunks[index].width()) + .sum(); + if expression_width > max_width { + max_width = expression_width; + } + }, + ); + + max_width + } + } + + pub(super) fn format_items_separated_by_comma( + &mut self, + items: Vec, + force_trailing_comma: bool, + surround_with_spaces: bool, + group: &mut ChunkGroup, + mut format_item: F, + ) where + F: FnMut(&mut Self, Item, &mut ChunkGroup), + { + let mut comments_chunk = self.skip_comments_and_whitespace_chunk(); + + // Handle leading block vs. line comments a bit differently. + if comments_chunk.string.trim().starts_with("/*") { + group.increase_indentation(); + if surround_with_spaces { + group.space_or_line(); + } else { + group.line(); + } + + // Note: there's no space before `{}` because it was just produced + comments_chunk.string = if surround_with_spaces { + comments_chunk.string.trim().to_string() + } else { + format!("{} ", comments_chunk.string.trim()) + }; + group.leading_comment(comments_chunk); + } else { + group.increase_indentation(); + if surround_with_spaces { + group.space_or_line(); + } else { + group.line(); + } + + group.trailing_comment(comments_chunk); + } + + for (index, expr) in items.into_iter().enumerate() { + if index > 0 { + group.text_attached_to_last_group(self.chunk(|formatter| { + formatter.write_comma(); + })); + let newlines_count_before_comment = self.following_newlines_count(); + group.text(self.chunk(|formatter| { + formatter.skip_whitespace(); + })); + if let Token::BlockComment(..) = &self.token { + // We let block comments be part of the item that's going to be formatted + } else { + // Line comments can be trailing or leading, depending on whether there are newlines before them + let comments_and_whitespace_chunk = self.skip_comments_and_whitespace_chunk(); + if !comments_and_whitespace_chunk.string.trim().is_empty() { + if newlines_count_before_comment > 0 { + group.line(); + group.leading_comment(comments_and_whitespace_chunk); + } else { + group.trailing_comment(comments_and_whitespace_chunk); + } + } + } + group.space_or_line(); + } + format_item(self, expr, group); + } + + let chunk = self.chunk(|formatter| { + formatter.skip_comments_and_whitespace(); + + // Trailing comma + if formatter.is_at(Token::Comma) { + formatter.bump(); + formatter.skip_comments_and_whitespace(); + } + }); + + // Make sure to put a trailing comma before the last parameter comments, if there were any + if !force_trailing_comma { + group.trailing_comma(); + } + + group.text(chunk); + + if force_trailing_comma { + group.text(TextChunk::new(",".to_string())); + } + + group.decrease_indentation(); + if surround_with_spaces { + group.space_or_line(); + } else { + group.line(); + } + } + + fn format_constructor(&mut self, constructor: ConstructorExpression) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.text(self.chunk(|formatter| { + formatter.format_type(constructor.typ); + formatter.write_space(); + formatter.write_left_brace(); + })); + + if constructor.fields.is_empty() { + if let Some(inner_group) = self.empty_block_contents_chunk() { + group.group(inner_group); + } + } else { + self.format_items_separated_by_comma( + constructor.fields, + false, // force trailing comma + true, // surround with spaces + &mut group, + |formatter, (name, value), chunks| { + chunks.text(formatter.chunk(|formatter| { + formatter.write_identifier(name); + formatter.skip_comments_and_whitespace(); + })); + + if formatter.is_at(Token::Colon) { + chunks.text(formatter.chunk(|formatter| { + formatter.write_token(Token::Colon); + formatter.write_space(); + })); + formatter.format_expression(value, chunks); + } + }, + ); + } + group.text(self.chunk(|formatter| { + formatter.write_right_brace(); + })); + + group + } + + fn format_member_access(&mut self, member_access: MemberAccessExpression) -> ChunkGroup { + let group_tag = self.new_group_tag(); + + let mut group = self.format_member_access_impl( + member_access, + false, // nested + group_tag, + ); + group.force_multiline_on_children_with_same_tag_if_multiline = true; + group + } + + fn format_member_access_impl( + &mut self, + member_access: MemberAccessExpression, + nested: bool, + group_tag: GroupTag, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.tag = Some(group_tag); + + if !nested { + group.push_indentation(); + } + + // If we have code like `foo.bar.baz.qux`, where `member_access.lhs` is also a MemberAccessExpression, + // we'll format it with the same tag. Once the lhs is not a MemberAccessExpression, we'll format it + // and add an increase in indentation, but just once so that it ends up being formatted like this + // in case it needs to be formatted in multiple lines: + // + // foo.bar + // .baz + // .qux + // + // Note that we do the same if the lhs is a MethodCallExpression. + // + // Also note that we don't format it like this: + // + // foo + // .bar + // .baz + // .qux + // + // For that, we check if the lhs'lhs is also a MemberAccess/MethodCall to determine where we need + // to put a line and an indentation. + let mut increase_indentation = false; + + match member_access.lhs.kind { + ExpressionKind::MemberAccess(lhs_member_access) => { + group.group(self.format_member_access_impl( + *lhs_member_access, + true, // nested + group_tag, + )); + } + ExpressionKind::MethodCall(lhs_method_call) => { + group.group(self.format_method_call_impl( + *lhs_method_call, + true, // nested + group_tag, + )); + } + _ => { + self.format_expression(member_access.lhs, &mut group); + + increase_indentation = true; + } + }; + + group.trailing_comment(self.skip_comments_and_whitespace_chunk()); + + if increase_indentation { + group.increase_indentation(); + } + + group.line(); + + group.text(self.chunk(|formatter| { + formatter.write_token(Token::Dot); + formatter.write_identifier_or_integer(member_access.rhs); + })); + + if !nested { + group.pop_indentation(); + } + + group + } + + fn format_cast(&mut self, cast_expression: CastExpression) -> ChunkGroup { + let mut group = ChunkGroup::new(); + self.format_expression(cast_expression.lhs, &mut group); + group.text(self.chunk(|formatter| { + formatter.write_space(); + formatter.write_keyword(Keyword::As); + formatter.write_space(); + formatter.format_type(cast_expression.r#type); + })); + group + } + + fn format_prefix(&mut self, prefix: PrefixExpression) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.text(self.chunk(|formatter| { + if let UnaryOp::MutableReference = prefix.operator { + formatter.write_current_token(); + formatter.bump(); + formatter.skip_comments_and_whitespace(); + formatter.write_current_token(); + formatter.bump(); + formatter.write_space(); + } else { + formatter.write_current_token(); + formatter.bump(); + } + })); + self.format_expression(prefix.rhs, &mut group); + group + } + + fn format_infix_expression(&mut self, infix: InfixExpression) -> ChunkGroup { + let group_tag = self.new_group_tag(); + + let mut group = self.format_infix_expression_with_group_tag( + infix, group_tag, false, // nested + ); + group.force_multiline_on_children_with_same_tag_if_multiline = true; + group + } + + fn format_infix_expression_with_group_tag( + &mut self, + infix: InfixExpression, + group_tag: GroupTag, + nested: bool, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.tag = Some(group_tag); + + if !nested { + group.push_indentation(); + } + + // If we have code like `a + b + c + d`, that's always parsed as `((a + b) + c) + d` where each + // parentheses denotes an InfixExpression. So, if the lhs of the current infix expression is also + // an infix expression with the same operator, we format it with the same tag. + // If the lhs is not an infix expression or has a different operator, we format it normally, + // and afterwards signal an increase in indentation. That way if this infix expression has + // to be formatted in multiple lines, we'll only indent after the first operand + // (we still produce "space or line" after each operator). + let increase_indentation = match infix.lhs.kind { + ExpressionKind::Infix(lhs_infix) if lhs_infix.operator == infix.operator => { + group.group(self.format_infix_expression_with_group_tag( + *lhs_infix, group_tag, true, // nested + )); + false + } + _ => { + self.format_expression(infix.lhs, &mut group); + true + } + }; + + // Indent right after the lhs so that if there's a trailing comment, + // the next line is indented correctly. + if increase_indentation { + group.increase_indentation(); + } + + let mut comment_chunk_after_lhs = self.skip_comments_and_whitespace_chunk(); + + // If the comment is not empty but doesn't have newlines, it's surely `/* comment */`. + // We format that with spaces surrounding it so it looks like `a /* comment */ + b`. + if !comment_chunk_after_lhs.string.trim().is_empty() + && !comment_chunk_after_lhs.has_newlines + { + // Note: there's no space after `{}` because a bit below comes "space_or_line". + comment_chunk_after_lhs.string = format!(" {}", comment_chunk_after_lhs.string.trim()); + group.text(comment_chunk_after_lhs); + } else { + group.trailing_comment(comment_chunk_after_lhs); + } + + group.space_or_line(); + group.text(self.chunk(|formatter| { + let tokens_count = + if infix.operator.contents == BinaryOpKind::ShiftRight { 2 } else { 1 }; + for _ in 0..tokens_count { + formatter.write_current_token(); + formatter.bump(); + } + formatter.write_space(); + })); + + self.format_expression(infix.rhs, &mut group); + + if !nested { + group.pop_indentation(); + } + + group + } + + pub(super) fn format_if_expression( + &mut self, + if_expression: IfExpression, + mut force_multiple_lines: bool, + ) -> ChunkGroup { + let group_tag = self.new_group_tag(); + let mut group = self.format_if_expression_with_group_tag( + if_expression, + &mut force_multiple_lines, + group_tag, + ); + + if force_multiple_lines || group.width() > self.config.single_line_if_else_max_width { + force_if_chunks_to_multiple_lines(&mut group, group_tag); + } + + group + } + + pub(super) fn format_if_expression_with_group_tag( + &mut self, + if_expression: IfExpression, + force_multiple_lines: &mut bool, + group_tag: GroupTag, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.tag = Some(group_tag); + + group.text(self.chunk(|formatter| { + formatter.write_keyword(Keyword::If); + formatter.write_space(); + })); + + self.format_expression(if_expression.condition, &mut group); + + let comment_chunk_after_condition = self.skip_comments_and_whitespace_chunk(); + if comment_chunk_after_condition.has_newlines { + *force_multiple_lines = true; + group.trailing_comment(comment_chunk_after_condition); + } else { + group.space(self); + } + + let ExpressionKind::Block(consequence_block) = if_expression.consequence.kind else { + panic!("Expected if expression consequence to be a block"); + }; + + if let Some(alternative) = &if_expression.alternative { + match &alternative.kind { + ExpressionKind::Block(block) => { + if block.statements.len() > 1 { + *force_multiple_lines = true; + } + } + ExpressionKind::If(..) => { + *force_multiple_lines = true; + } + _ => panic!("Unexpected if alternative expression kind"), + } + } + + let mut consequence_group = + self.format_block_expression(consequence_block, *force_multiple_lines); + consequence_group.tag = Some(group_tag); + group.group(consequence_group); + + if let Some(alternative) = if_expression.alternative { + group.text(self.chunk(|formatter| { + formatter.write_space(); + formatter.write_keyword(Keyword::Else); + })); + + let comment_chunk_after_else = self.skip_comments_and_whitespace_chunk(); + if comment_chunk_after_else.has_newlines { + *force_multiple_lines = true; + group.trailing_comment(comment_chunk_after_else); + } else { + group.space(self); + } + + let mut alternative_group = match alternative.kind { + ExpressionKind::Block(block) => { + self.format_block_expression(block, *force_multiple_lines) + } + ExpressionKind::If(if_expression) => self.format_if_expression_with_group_tag( + *if_expression, + force_multiple_lines, + group_tag, + ), + _ => panic!("Unexpected if alternative expression kind"), + }; + + alternative_group.tag = Some(group_tag); + group.group(alternative_group); + } + + group + } + + fn format_index_expression(&mut self, index: IndexExpression) -> ChunkGroup { + let mut group = ChunkGroup::new(); + self.format_expression(index.collection, &mut group); + group.text(self.chunk(|formatter| { + formatter.write_left_bracket(); + })); + + // If we have: + // + // foo[ // bar + // 1] + // + // and there were newlines in the comment section, we format it like this: + // + // foo[ + // // bar + // 1 + // ] + // + // That is, we first put a newline before the comment so it looks a bit better. + // This is a rare scenario, but we had a test for this before the formatter was + // rewritten, so... + let comments_chunk = self.skip_comments_and_whitespace_chunk(); + let comments_chunk_has_newlines = comments_chunk.has_newlines; + + if comments_chunk_has_newlines { + group.increase_indentation(); + group.line(); + } + + group.leading_comment(comments_chunk); + + self.format_expression(index.index, &mut group); + + if comments_chunk_has_newlines { + group.decrease_indentation(); + group.line(); + } + + group.text(self.chunk(|formatter| { + formatter.write_right_bracket(); + })); + group + } + + fn format_call(&mut self, call: CallExpression) -> ChunkGroup { + let mut group = ChunkGroup::new(); + + self.format_expression(*call.func, &mut group); + + group.text(self.chunk(|formatter| { + if call.is_macro_call { + formatter.write_token(Token::Bang); + } + formatter.write_left_paren(); + })); + + group.kind = GroupKind::ExpressionList { + prefix_width: group.width(), + expressions_count: call.arguments.len(), + }; + + // Format arguments in a separate group so we can calculate the arguments + // width and determine if we need to format this call in multiple lines. + let mut args_group = ChunkGroup::new(); + self.format_expressions_separated_by_comma( + call.arguments, + false, // force trailing comma + &mut args_group, + ); + + if args_group.width() > self.config.fn_call_width { + group.force_multiple_lines = true; + } + + // We no longer need this subgroup, so put all its chunks into the main chunks + group.chunks.extend(args_group.chunks); + + group.text(self.chunk(|formatter| { + formatter.write_right_paren(); + })); + + group + } + + fn format_method_call(&mut self, method_call: MethodCallExpression) -> ChunkGroup { + let group_tag = self.new_group_tag(); + + let mut group = self.format_method_call_impl( + method_call, + false, // nested + group_tag, + ); + group.force_multiline_on_children_with_same_tag_if_multiline = true; + group + } + + fn format_method_call_impl( + &mut self, + method_call: MethodCallExpression, + nested: bool, + group_tag: GroupTag, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.tag = Some(group_tag); + + if !nested { + group.push_indentation(); + } + + // The logic here is similar to that of `format_member_access_with_group_tag`, so + // please that function inner comments for details. + let mut increase_indentation_before_dot = false; + + match method_call.object.kind { + ExpressionKind::MethodCall(lhs_method_call) => { + group.group(self.format_method_call_impl( + *lhs_method_call, + true, // nested + group_tag, + )); + } + ExpressionKind::MemberAccess(lhs_member_access) => { + group.group(self.format_member_access_impl( + *lhs_member_access, + true, // nested + group_tag, + )); + } + _ => { + self.format_expression(method_call.object, &mut group); + + increase_indentation_before_dot = true; + } + } + + group.trailing_comment(self.skip_comments_and_whitespace_chunk()); + + if increase_indentation_before_dot { + group.increase_indentation(); + } + + group.line(); + + group.text(self.chunk(|formatter| { + formatter.write_token(Token::Dot); + formatter.write_identifier(method_call.method_name); + if method_call.is_macro_call { + formatter.write_token(Token::Bang); + } + if let Some(generics) = method_call.generics { + formatter.format_turbofish(generics); + } + formatter.write_left_paren(); + })); + + group.kind = GroupKind::MethodCall { + width_until_left_paren_inclusive: group.width(), + has_newlines_before_left_paren: group.has_newlines(), + lhs: nested, + }; + + let mut args_group = ChunkGroup::new(); + args_group.kind = GroupKind::ExpressionList { + prefix_width: 0, + expressions_count: method_call.arguments.len(), + }; + self.format_expressions_separated_by_comma( + method_call.arguments, + false, // force trailing comma + &mut args_group, + ); + group.group(args_group); + + group.text(self.chunk(|formatter| { + formatter.write_right_paren(); + })); + + if !nested { + group.pop_indentation(); + } + + group + } + + pub(super) fn format_block_expression( + &mut self, + block: BlockExpression, + force_multiple_lines: bool, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.text(self.chunk(|formatter| { + formatter.write_left_brace(); + })); + self.format_block_expression_contents(block, force_multiple_lines, &mut group); + group.text(self.chunk(|formatter| { + formatter.write_right_brace(); + })); + group + } + + pub(super) fn format_block_expression_contents( + &mut self, + block: BlockExpression, + force_multiple_lines: bool, + group: &mut ChunkGroup, + ) { + if block.is_empty() { + if let Some(block_group) = self.empty_block_contents_chunk() { + group.chunks.extend(block_group.chunks); + } + } else { + self.format_non_empty_block_expression_contents(block, force_multiple_lines, group); + } + } + + pub(super) fn format_non_empty_block_expression_contents( + &mut self, + block: BlockExpression, + force_multiple_lines: bool, + group: &mut ChunkGroup, + ) { + group.force_multiple_lines = force_multiple_lines || block.statements.len() > 1; + let surround_with_spaces = !group.force_multiple_lines && block.statements.len() == 1; + + group.increase_indentation(); + if surround_with_spaces { + group.space_or_line(); + } else { + group.line(); + } + + for (index, statement) in block.statements.into_iter().enumerate() { + let mut ignore_next = false; + + if index > 0 { + let count = self.following_newlines_count(); + if count > 0 { + // If newlines follow, we first add a line, then add the comment chunk + group.lines(count > 1); + group.leading_comment(self.chunk(|formatter| { + formatter.skip_comments_and_whitespace_writing_multiple_lines_if_found(); + })); + ignore_next = self.ignore_next; + } else { + // Otherwise, add the comment first as it's a trailing comment + group.trailing_comment(self.chunk(|formatter| { + formatter.skip_comments_and_whitespace_writing_multiple_lines_if_found(); + })); + ignore_next = self.ignore_next; + group.line(); + } + } + + self.format_statement(statement, group, ignore_next); + } + + // See how many newlines follow the last statement + let count = self.following_newlines_count(); + + group.text(self.chunk(|formatter| { + formatter.skip_whitespace(); + })); + + // After skipping whitespace we check if there's a comment. If so, we respect + // how many lines were before that comment. + if count > 0 && matches!(self.token, Token::LineComment(..) | Token::BlockComment(..)) { + group.lines(count > 1); + } + + // Finally format the comment, if any + group.text(self.chunk(|formatter| { + formatter.skip_comments_and_whitespace_writing_multiple_lines_if_found(); + })); + + group.decrease_indentation(); + + if surround_with_spaces { + group.space_or_line(); + } else { + group.line(); + } + } + + pub(super) fn empty_block_contents_chunk(&mut self) -> Option { + let mut group = ChunkGroup::new(); + group.increase_indentation(); + + let newlines_count = self.following_newlines_count(); + + let mut chunk = self.chunk(|formatter| { + formatter.skip_comments_and_whitespace_writing_multiple_lines_if_found(); + }); + + if chunk.string.trim().is_empty() { + // We only found whitespace until the next non-whitespace-non-comment token, + // so there's nothing to write. + None + } else { + // If we have a trailing comment, preserve it in the same line + if newlines_count == 0 && !chunk.string.trim_start().starts_with("//") { + chunk.string = format!(" {} ", chunk.string.trim()); + } + group.text(chunk); + group.decrease_indentation(); + group.line(); + Some(group) + } + } +} + +impl<'a> Formatter<'a> { + pub(super) fn format_empty_block_contents(&mut self) { + if let Some(chunks) = self.chunk_formatter().empty_block_contents_chunk() { + self.format_chunk_group(chunks); + } + } +} + +fn force_if_chunks_to_multiple_lines(group: &mut ChunkGroup, group_tag: GroupTag) { + if group.tag == Some(group_tag) { + group.force_multiple_lines = true; + } + + for chunk in group.chunks.iter_mut() { + if let Chunk::Group(inner_group) = chunk { + force_if_chunks_to_multiple_lines(inner_group, group_tag); + } + } +} + +#[cfg(test)] +mod tests { + use crate::{assert_format, assert_format_with_config, assert_format_with_max_width, Config}; + + #[test] + fn format_unit() { + let src = "global x = ( ) ;"; + let expected = "global x = ();\n"; + assert_format(src, expected); + } + + #[test] + fn format_false() { + let src = "global x = false ;"; + let expected = "global x = false;\n"; + assert_format(src, expected); + } + + #[test] + fn format_true() { + let src = "global x = true ;"; + let expected = "global x = true;\n"; + assert_format(src, expected); + } + + #[test] + fn format_integer() { + let src = "global x = 42 ;"; + let expected = "global x = 42;\n"; + assert_format(src, expected); + } + + #[test] + fn format_negative_integer() { + let src = "global x = - 42 ;"; + let expected = "global x = -42;\n"; + assert_format(src, expected); + } + + #[test] + fn format_ref_mut_integer() { + let src = "global x = & mut 42 ;"; + let expected = "global x = &mut 42;\n"; + assert_format(src, expected); + } + + #[test] + fn format_hex_integer() { + let src = "global x = 0xff ;"; + let expected = "global x = 0xff;\n"; + assert_format(src, expected); + } + + #[test] + fn format_string() { + let src = "global x = \"hello\" ;"; + let expected = "global x = \"hello\";\n"; + assert_format(src, expected); + } + + #[test] + fn format_fmtstr() { + let src = "global x = f\"hello\" ;"; + let expected = "global x = f\"hello\";\n"; + assert_format(src, expected); + } + + #[test] + fn format_standard_array() { + let src = "global x = [ 1 , 2 , 3 , ] ;"; + let expected = "global x = [1, 2, 3];\n"; + assert_format(src, expected); + } + + #[test] + fn format_standard_slice() { + let src = "global x = & [ 1 , 2 , 3 , ] ;"; + let expected = "global x = &[1, 2, 3];\n"; + assert_format(src, expected); + } + + #[test] + fn format_repeated_array() { + let src = "global x = [ 1 ; 3 ] ;"; + let expected = "global x = [1; 3];\n"; + assert_format(src, expected); + } + + #[test] + fn format_long_array_in_global() { + let src = "global x = [ 1 , 2 , 3 , 4, 5, ] ;"; + let expected = "global x = + [1, 2, 3, 4, 5]; +"; + assert_format_with_max_width(src, expected, 20); + } + + #[test] + fn format_long_array_in_global_in_mod() { + let src = "mod moo { mod bar { global x = [ 1 , 2 , 3 , 4, 5, ] ; } }"; + let expected = "mod moo { + mod bar { + global x = [ + 1, 2, 3, 4, + 5, + ]; + } +} +"; + assert_format_with_max_width(src, expected, 25); + } + + #[test] + fn format_long_array_in_global_2() { + let src = "global x = [ 1 , 2 , 3 , 4, 5, ] ; + +global y = 1; + "; + let expected = "global x = + [1, 2, 3, 4, 5]; + +global y = 1; +"; + assert_format_with_max_width(src, expected, 20); + } + + #[test] + fn format_very_long_array_in_global() { + let src = "global x = [ 1 , 2 , 3 , 4, 5, 6, 789, 123, 234, 345] ;"; + let expected = "global x = [ + 1, 2, 3, 4, 5, 6, + 789, 123, 234, 345, +]; +"; + assert_format_with_max_width(src, expected, 25); + } + + #[test] + fn format_long_array_element() { + let src = "global x = [ 123, 1234, 12345, 123, 1234, 12345, 123456, 123] ;"; + let expected = "global x = [ + 123, + 1234, + 12345, + 123, + 1234, + 12345, + 123456, + 123, +]; +"; + + let config = + Config { short_array_element_width_threshold: 5, max_width: 30, ..Default::default() }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn format_short_array_with_block_comment_before_elements() { + let src = "global x = [ /* one */ 1, /* two */ 2 ] ;"; + let expected = "global x = [/* one */ 1, /* two */ 2];\n"; + + assert_format(src, expected); + } + + #[test] + fn format_long_array_with_block_comment_before_elements() { + let src = "global x = [ /* one */ 1, /* two */ 123456789012345, 3, 4 ] ;"; + let expected = "global x = [ + /* one */ 1, + /* two */ 123456789012345, + 3, + 4, +]; +"; + + let config = + Config { short_array_element_width_threshold: 5, max_width: 30, ..Config::default() }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn format_long_array_with_line_comment_before_elements() { + let src = "global x = [ + // one + 1, + // two + 123456789012345, + 3, + 4, +]; +"; + let expected = "global x = [ + // one + 1, + // two + 123456789012345, + 3, + 4, +]; +"; + + let config = + Config { short_array_element_width_threshold: 5, max_width: 30, ..Config::default() }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn format_cast() { + let src = "global x = 1 as u8 ;"; + let expected = "global x = 1 as u8;\n"; + assert_format(src, expected); + } + + #[test] + fn format_variable() { + let src = "global x = y ;"; + let expected = "global x = y;\n"; + assert_format(src, expected); + } + + #[test] + fn format_tuple() { + let src = "global x = ( 1 , 2 , 3 , ) ;"; + let expected = "global x = (1, 2, 3);\n"; + assert_format(src, expected); + } + + #[test] + fn format_tuple_length_one() { + let src = "global x = ( 1 , ) ;"; + let expected = "global x = (1,);\n"; + assert_format(src, expected); + } + + #[test] + fn format_as_trait_path() { + let src = "global x = < i32 as foo > :: bar ;"; + let expected = "global x = ::bar;\n"; + assert_format(src, expected); + } + + #[test] + fn format_index() { + let src = "global x = foo [ bar ] ;"; + let expected = "global x = foo[bar];\n"; + assert_format(src, expected); + } + + #[test] + fn format_long_index() { + let src = "global x = foo [ bar [ baz [ qux [ one [ two ]]]] ] ; global y = 1;"; + let expected = "global x = foo[bar[baz[ + qux[one[two]]]]]; +global y = 1; +"; + assert_format_with_max_width(src, expected, 25); + } + + #[test] + fn format_long_index_2() { + let src = "global x = foo [ bar ] [ baz ] [ qux ] [ one ] [ two ] ; global y = 1;"; + let expected = "global x = foo[bar][baz] + [qux][one][two]; +global y = 1; +"; + assert_format_with_max_width(src, expected, 25); + } + + #[test] + fn format_prefix() { + let src = "global x = - a ;"; + let expected = "global x = -a;\n"; + assert_format(src, expected); + } + + #[test] + fn format_infix() { + let src = "global x = a + b ;"; + let expected = "global x = a + b;\n"; + assert_format(src, expected); + } + + #[test] + fn format_long_infix_same_operator_1() { + let src = "global x = one + two + three;"; + let expected = "global x = one + + two + + three; +"; + assert_format_with_max_width(src, expected, "one + two + three".len() - 1); + } + + #[test] + fn format_long_infix_same_operator_2() { + let src = "global x = one + two + three + four;"; + let expected = "global x = one + + two + + three + + four; +"; + assert_format_with_max_width(src, expected, "one + two + three + four".len() - 1); + } + + #[test] + fn format_long_infix_same_operator_3() { + let src = "fn foo() { one + two + three + four }"; + let expected = "fn foo() { + one + + two + + three + + four +} +"; + assert_format_with_max_width(src, expected, "one + two + three + four".len() - 1); + } + + #[test] + fn format_infix_with_trailing_comments() { + let src = "fn foo() { + let x = 1 // one ++ 2 // two ++ 3; // three +} +"; + let expected = "fn foo() { + let x = 1 // one + + 2 // two + + 3; // three +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_block() { + let src = "global x = { } ;"; + let expected = "global x = {};\n"; + assert_format(src, expected); + } + + #[test] + fn format_block_with_one_statement() { + let src = "global x = { 1 } ;"; + let expected = "global x = { 1 };\n"; + assert_format(src, expected); + } + + #[test] + fn format_block_with_two_statements() { + let src = "global x = { 1; 2 } ;"; + let expected = "global x = { + 1; + 2 +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_call() { + let src = "global x = foo :: bar ( 1, 2 ) ;"; + let expected = "global x = foo::bar(1, 2);\n"; + assert_format(src, expected); + } + + #[test] + fn format_call_with_turbofish() { + let src = "global x = foo :: bar :: < Field, i32 > ( 1, 2 ) ;"; + let expected = "global x = foo::bar::(1, 2);\n"; + assert_format(src, expected); + } + + #[test] + fn format_call_with_maximum_width() { + let src = "global x = foo :: bar ( 1, 2, 3 ) ;"; + let expected = "global x = foo::bar( + 1, + 2, + 3, +);\n"; + + let config = Config { fn_call_width: "1, 2, 3".len() - 1, ..Default::default() }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn format_call_with_maximum_width_2() { + let src = "global x = foo::bar::baz( );"; + let expected = "global x = foo::bar::baz();\n"; + assert_format_with_max_width(src, expected, "foo::bar::baz".len() - 1); + } + + #[test] + fn format_nested_call_with_maximum_width() { + let src = "fn foo() { foo(bar(123, 456, 789)) } "; + let expected = "fn foo() { + foo(bar( + 123, + 456, + 789, + )) +} +"; + assert_format_with_max_width(src, expected, " foo(bar(".len()); + } + + #[test] + fn format_nested_call_with_maximum_width_2() { + let src = "fn foo() { + let note_interface_impl = s.as_type().get_trait_impl(quote { crate::note::note_interface::NoteInterface<$serialized_len_type> } + .as_trait_constraint()); +} +"; + let expected = "fn foo() { + let note_interface_impl = s.as_type().get_trait_impl( + quote { crate::note::note_interface::NoteInterface<$serialized_len_type> } + .as_trait_constraint(), + ); +} +"; + assert_format(src, expected); + } + + #[test] + fn format_nested_call_with_maximum_width_3() { + let src = "mod foo { + fn bar() { + assert(foo(bar.baz(x12345))); + } +} +"; + let expected = "mod foo { + fn bar() { + assert(foo(bar.baz( + x12345, + ))); + } +} +"; + assert_format_with_max_width(src, expected, 33); + } + + #[test] + fn format_nested_call_with_maximum_width_4() { + let src = "mod foo { + fn bar() { + assert(foo(bar_baz(x1, x2))); + } +} +"; + let expected = "mod foo { + fn bar() { + assert(foo(bar_baz( + x1, + x2, + ))); + } +} +"; + assert_format_with_max_width(src, expected, 33); + } + + #[test] + fn format_call_with_maximum_width_comma_exceeds() { + let src = "global x = foo::bar( + baz::qux(1, 2, 3), +);"; + let expected = "global x = foo::bar( + baz::qux( + 1, + 2, + 3, + ), +); +"; + assert_format_with_max_width(src, expected, " baz::qux(1, 2, 3),".len() - 1); + } + + #[test] + fn format_call_with_maximum_width_comma_exceeds_2() { + let src = "global x = foo::bar( + |x, y| { some_chunk_of_code }, +);"; + let expected = "global x = foo::bar(|x, y| { + some_chunk_of_code +}); +"; + assert_format_with_max_width(src, expected, " |x, y| { some_chunk_of_code },".len() - 1); + } + + #[test] + fn format_nested_call_max_width() { + let src = "global _callStackItem1 = context.call_public_function( + context.this_address(), + comptime { + FunctionSelector::from_signature(\"broadcast(Field)\") + }, + [owner] + );"; + let expected = "global _callStackItem1 = context.call_public_function( + context.this_address(), + comptime { FunctionSelector::from_signature(\"broadcast(Field)\") }, + [owner], +); +"; + assert_format(src, expected); + } + + #[test] + fn format_method_call() { + let src = "global x = bar . baz ( 1, 2 ) ;"; + let expected = "global x = bar.baz(1, 2);\n"; + assert_format(src, expected); + } + + #[test] + fn format_method_call_with_long_arguments() { + let src = "global x = bar . baz ( 123456789, 123456789, 123456789, 123456789, 123456789, 123456789, 123456789 ) ;"; + let expected = "global x = bar.baz( + 123456789, + 123456789, + 123456789, + 123456789, + 123456789, + 123456789, + 123456789, +); +"; + assert_format_with_max_width(src, expected, 40); + } + + #[test] + fn format_method_call_with_generics() { + let src = "global x = bar . baz :: < T > ( 1, 2 ) ;"; + let expected = "global x = bar.baz::(1, 2);\n"; + assert_format(src, expected); + } + + #[test] + fn format_method_call_chain() { + let src = "global x = bar . baz ( 1, 2 ) . qux ( 1 , 2, 3) . one ( 5, 6) ;"; + let expected = "global x = bar + .baz(1, 2) + .qux(1, 2, 3) + .one(5, 6); +"; + assert_format_with_max_width(src, expected, 25); + } + + #[test] + fn format_method_call_chain_2() { + let src = "fn foo() { bar . baz ( 1, 2 ) . qux ( 1 , 2, 3) . one ( 5, 6) }"; + let expected = "fn foo() { + bar.baz(1, 2).qux(1, 2, 3).one( + 5, + 6, + ) +} +"; + assert_format_with_max_width(src, expected, " bar.baz(1, 2).qux(1, 2, 3).one(".len()); + } + + #[test] + fn format_method_call_chain_3() { + let src = "fn foo() { assert(p4_affine.eq(Gaffine::new(6890855772600357754907169075114257697580319025794532037257385534741338397365, 4338620300185947561074059802482547481416142213883829469920100239455078257889))); }"; + let expected = "fn foo() { + assert(p4_affine.eq(Gaffine::new( + 6890855772600357754907169075114257697580319025794532037257385534741338397365, + 4338620300185947561074059802482547481416142213883829469920100239455078257889, + ))); +} +"; + assert_format(src, expected); + } + + #[test] + fn format_method_call_with_maximum_width() { + let src = "global x = foo::bar.baz( );"; + let expected = "global x = foo::bar + .baz(); +"; + assert_format_with_max_width(src, expected, "foo::bar.baz".len() - 1); + } + + #[test] + fn format_nested_method_call_with_maximum_width() { + let src = "fn foo() { foo.bar(baz.qux(123, 456, 789)) } "; + let expected = "fn foo() { + foo.bar(baz.qux( + 123, + 456, + 789, + )) +} +"; + assert_format_with_max_width(src, expected, " foo.bar(bar.qux(".len()); + } + + #[test] + fn format_nested_method_call_with_maximum_width_2() { + let src = "fn foo() { + assert( + p4_affine.eq(Gaffine::new( + 6890855772600357754907169075114257697580319025794532037257385534741338397365, + 4338620300185947561074059802482547481416142213883829469920100239455078257889, + )), + ); +} +"; + let expected = "fn foo() { + assert(p4_affine.eq(Gaffine::new( + 6890855772600357754907169075114257697580319025794532037257385534741338397365, + 4338620300185947561074059802482547481416142213883829469920100239455078257889, + ))); +} +"; + assert_format(src, expected); + } + + #[test] + fn format_member_access() { + let src = "global x = bar . baz ;"; + let expected = "global x = bar.baz;\n"; + assert_format(src, expected); + } + + #[test] + fn format_long_member_access_alone() { + let src = "global x = foo . bar . baz . qux . final ;"; + let expected = "global x = foo + .bar + .baz + .qux + .final; +"; + assert_format_with_max_width(src, expected, "foo.bar.baz.qux.final".len() - 1); + } + + #[test] + fn format_long_member_access_and_method_call_chain() { + let src = "global x = foo . bar(1, 2) . baz . qux(2, 3) . this_is_a_long_name ;"; + let expected = "global x = foo + .bar(1, 2) + .baz + .qux(2, 3) + .this_is_a_long_name; +"; + assert_format_with_max_width(src, expected, 25); + } + + #[test] + fn format_long_member_access_and_method_call_chain_2() { + let src = "fn burn() { + storage + .at(from) + .sub(from_keys.npk_m, U128::from_integer(amount)) + .emit(encode_and_encrypt_note!()); +} +"; + let expected = "fn burn() { + storage.at(from).sub(from_keys.npk_m, U128::from_integer(amount)).emit( + encode_and_encrypt_note!(), + ); +} +"; + assert_format(src, expected); + } + + #[test] + fn format_tuple_member_access() { + let src = "global x = bar . 0 ;"; + let expected = "global x = bar.0;\n"; + assert_format(src, expected); + } + + #[test] + fn format_parenthesized() { + let src = "global x = ( 1 ) ;"; + let expected = "global x = (1);\n"; + assert_format(src, expected); + } + + #[test] + fn format_unsafe_one_expression() { + let src = "global x = unsafe { + 1 } ;"; + let expected = "global x = unsafe { 1 };\n"; + assert_format(src, expected); + } + + #[test] + fn format_unsafe_two_expressions() { + let src = "global x = unsafe { + 1; 2 } ;"; + let expected = "global x = unsafe { + 1; + 2 +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_unsafe_with_doc_comment() { + let src = "fn foo() { + /// Comment + unsafe { 1 } }"; + let expected = "fn foo() { + /// Comment + unsafe { + 1 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_comptime_one_expression() { + let src = "global x = comptime { 1 } ;"; + let expected = "global x = comptime { 1 };\n"; + assert_format(src, expected); + } + + #[test] + fn format_comptime_two_expressions() { + let src = "global x = comptime { 1; 2 } ;"; + let expected = "global x = comptime { + 1; + 2 +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_constructor() { + let src = "global x = Foo { } ;"; + let expected = "global x = Foo {};\n"; + assert_format(src, expected); + } + + #[test] + fn format_constructor() { + let src = "global x = Foo { one: 1 , two : 2 , three } ;"; + let expected = "global x = Foo { one: 1, two: 2, three };\n"; + assert_format(src, expected); + } + + #[test] + fn format_constructor_with_turbofish() { + let src = "global x = Foo :: < Bar > { one } ;"; + let expected = "global x = Foo:: { one };\n"; + assert_format(src, expected); + } + + #[test] + fn format_type_path() { + let src = "global x = Field :: max ;"; + let expected = "global x = Field::max;\n"; + assert_format(src, expected); + } + + #[test] + fn format_type_path_with_turbofish() { + let src = "global x = Field :: max :: < i32 > ;"; + let expected = "global x = Field::max::;\n"; + assert_format(src, expected); + } + + #[test] + fn format_if_expression_without_else_one_expression() { + let src = "global x = if 1 { 2 } ;"; + let expected = "global x = if 1 { 2 };\n"; + assert_format(src, expected); + } + + #[test] + fn format_if_expression_without_else_two_expressions() { + let src = "global x = if 1 { 2; 3 } ;"; + let expected = "global x = if 1 { + 2; + 3 +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_if_expression_with_else() { + let src = "global x = if 1 { 2 } else { 3 };"; + let expected = "global x = if 1 { 2 } else { 3 };\n"; + assert_format(src, expected); + } + + #[test] + fn format_if_expression_with_else_multiple_exprs() { + let src = "global x = if 1 { 2 } else { 3; 4 };"; + let expected = "global x = if 1 { + 2 +} else { + 3; + 4 +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_if_expression_else_if() { + let src = "global x = if 1 { 2 } else if 3 { 4 };"; + let expected = "global x = if 1 { + 2 +} else if 3 { + 4 +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_if_with_configurable_maximum_if_width() { + let src = "global x = if 123 { 456 } else { 789 };"; + let expected = "global x = if 123 { + 456 +} else { + 789 +};\n"; + + let config = Config { + single_line_if_else_max_width: "if 123 { 456 } else { 789 }".len() - 1, + ..Config::default() + }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn format_if_with_configurable_maximum_if_width_2() { + let src = "global x = if foo(123) { 456 } else { 789 };"; + let expected = "global x = if foo(123) { + 456 +} else { + 789 +};\n"; + + let config = Config { + single_line_if_else_max_width: "if foo(123) { 456 } else { 789 }".len() - 1, + ..Config::default() + }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn format_quote() { + let src = "global x = quote { 1 2 3 $four $(five) };"; + let expected = "global x = quote { 1 2 3 $four $(five) };\n"; + assert_format(src, expected); + } + + #[test] + fn format_quote_with_newlines() { + let src = "fn foo() { + quote { + + foo + + bar + + } +} +"; + let expected = src; + assert_format(src, expected); + } + + #[test] + fn format_quote_with_bracket_delimiter() { + let src = "global x = quote [ 1 2 3 $four $(five) ];"; + let expected = "global x = quote [ 1 2 3 $four $(five) ];\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_no_parameters() { + let src = "global x = | | 1 ;"; + let expected = "global x = || 1;\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_with_parameters() { + let src = "global x = | x , y : Field , z | 1 ;"; + let expected = "global x = |x, y: Field, z| 1;\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_with_block_simplifies() { + let src = "global x = | | { 1 } ;"; + let expected = "global x = || 1;\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_with_block_does_not_simplify_if_it_ends_with_semicolon() { + let src = "global x = | | { 1; } ;"; + let expected = "global x = || { 1; };\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_with_block_does_not_simplify_if_it_has_return_type() { + let src = "global x = | | -> i32 { 1 } ;"; + let expected = "global x = || -> i32 { 1 };\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_with_simplifies_block_with_quote() { + let src = "global x = | | { quote { 1 } } ;"; + let expected = "global x = || quote { 1 };\n"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_with_block_simplifies_inside_arguments_list() { + let src = "global x = some_call(this_is_a_long_argument, | | { 1 });"; + let expected = "global x = some_call( + this_is_a_long_argument, + || 1, +); +"; + assert_format_with_max_width(src, expected, 20); + } + + #[test] + fn format_lambda_with_block_multiple_statements() { + let src = "global x = | a, b | { 1; 2 } ;"; + let expected = "global x = |a, b| { + 1; + 2 +}; +"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_as_last_call_argument() { + let src = "global x = foo(1, |x| { 1; 2 });"; + let expected = "global x = foo(1, |x| { + 1; + 2 +}); +"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_as_last_method_call_argument() { + let src = "global x = foo.bar(1, |x| { 1; 2 });"; + let expected = "global x = foo.bar(1, |x| { + 1; + 2 +}); +"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_as_last_method_call_argument_2() { + let src = "fn foo(){ + m.structs().any(|s: StructDefinition| s.has_named_attribute(\"storage\") | s.has_named_attribute(\"storage_no_init\"), + ) +} +"; + let expected = "fn foo() { + m.structs().any(|s: StructDefinition| { + s.has_named_attribute(\"storage\") | s.has_named_attribute(\"storage_no_init\") + }) +} +"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_as_last_method_call_argument_3() { + let src = "mod moo { + fn foo() { + let mut sorted_write_tuples = unsafe { + get_sorted_tuple( + final_public_data_writes.storage, + |(_, leaf_a): (u32, PublicDataTreeLeaf), (_, leaf_b): (u32, PublicDataTreeLeaf)| full_field_less_than( + 1, 2, + ), + ) + }; + } +} +"; + let expected = "mod moo { + fn foo() { + let mut sorted_write_tuples = unsafe { + get_sorted_tuple( + final_public_data_writes.storage, + |(_, leaf_a): (u32, PublicDataTreeLeaf), (_, leaf_b): (u32, PublicDataTreeLeaf)| { + full_field_less_than(1, 2) + }, + ) + }; + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_as_last_method_call_chain_argument() { + let src = "global x = foo.bar(1).baz(2, |x| { 1; 2 });"; + let expected = "global x = foo.bar(1).baz(2, |x| { + 1; + 2 +}); +"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_as_last_method_call_chain_argument_2() { + let src = "fn foo() { expr.as_unsafe().map(|exprs| { a; aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }) } + "; + let expected = "fn foo() { + expr.as_unsafe().map(|exprs| { + a; + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + }) +} +"; + assert_format(src, expected); + } + + #[test] + fn format_lambda_as_last_method_call_has_to_wrap() { + let src = "global foo = bar(1, 2, 3, |argument| { 1; 2 });"; + let expected = "global foo = bar( + 1, + 2, + 3, + |argument| { + 1; + 2 + }, +); +"; + assert_format_with_max_width(src, expected, src.len() - 10); + } + + #[test] + fn removes_nested_parens() { + let src = "global x = ( ( ( ( ) ) ) ) ;"; + let expected = "global x = (());\n"; + assert_format(src, expected); + } + + #[test] + fn does_not_remove_nested_parens_if_not_told_so() { + let src = "global x = ( ( ( ( ) ) ) ) ;"; + let expected = "global x = (((())));\n"; + + let config = Config { remove_nested_parens: false, ..Config::default() }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn attaches_comma_to_last_group() { + let src = " mod moo { + fn foo() { + [ + Foo { a: 1 }, Foo { a: 1 } + ]; + bar; + } +} +"; + let expected = "mod moo { + fn foo() { + [ + Foo { + a: 1, + }, + Foo { + a: 1, + }, + ]; + bar; + } +} +"; + assert_format_with_max_width(src, expected, " Foo { a: 1 },".len() - 1); + } +} diff --git a/tooling/nargo_fmt/src/formatter/function.rs b/tooling/nargo_fmt/src/formatter/function.rs new file mode 100644 index 00000000000..ca905f3dcf8 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/function.rs @@ -0,0 +1,621 @@ +use noirc_frontend::{ + ast::{ + BlockExpression, FunctionReturnType, Ident, ItemVisibility, NoirFunction, Param, + UnresolvedGenerics, UnresolvedTraitConstraint, Visibility, + }, + token::{Attributes, Keyword, Token}, +}; + +use super::Formatter; +use crate::chunks::{ChunkGroup, TextChunk}; + +pub(super) struct FunctionToFormat { + pub(super) attributes: Attributes, + pub(super) visibility: ItemVisibility, + pub(super) name: Ident, + pub(super) generics: UnresolvedGenerics, + pub(super) parameters: Vec, + pub(super) return_type: FunctionReturnType, + pub(super) return_visibility: Visibility, + pub(super) where_clause: Vec, + pub(super) body: Option, + pub(super) skip_visibility: bool, +} + +impl<'a> Formatter<'a> { + pub(super) fn format_function(&mut self, func: NoirFunction, skip_visibility: bool) { + self.format_function_impl(FunctionToFormat { + attributes: func.def.attributes, + visibility: func.def.visibility, + name: func.def.name, + generics: func.def.generics, + parameters: func.def.parameters, + return_type: func.def.return_type, + return_visibility: func.def.return_visibility, + where_clause: func.def.where_clause, + body: Some(func.def.body), + skip_visibility, + }); + } + + pub(super) fn format_function_impl(&mut self, func: FunctionToFormat) { + let has_where_clause = !func.where_clause.is_empty(); + + self.format_attributes(func.attributes); + self.write_indentation(); + self.format_function_modifiers(func.visibility, func.skip_visibility); + self.write_keyword(Keyword::Fn); + self.write_space(); + self.write_identifier(func.name); + self.format_generics(func.generics); + self.write_left_paren(); + + // When the function has no parameters we can format everything in a single line + if func.parameters.is_empty() { + self.increase_indentation(); + self.skip_comments_and_whitespace(); + self.decrease_indentation(); + + let group = ChunkGroup::new(); + self.format_function_right_paren_until_left_brace_or_semicolon( + func.return_type, + func.return_visibility, + has_where_clause, + false, // has parameters + func.body.is_none(), // semicolon + group, + ); + } else { + let mut group = ChunkGroup::new(); + self.format_function_parameters(func.parameters, &mut group); + self.format_function_right_paren_until_left_brace_or_semicolon( + func.return_type, + func.return_visibility, + has_where_clause, + true, // has parameters + func.body.is_none(), // semicolon + group, + ); + } + + if has_where_clause { + self.format_where_clause( + func.where_clause, + func.body.is_some(), // write trailing comma and newline + ); + if func.body.is_some() { + self.write_left_brace(); + } else { + self.write_semicolon(); + } + } + + if let Some(body) = func.body { + self.format_function_body(body); + self.write_right_brace(); + } + } + + pub(super) fn format_function_modifiers( + &mut self, + visibility: ItemVisibility, + skip_visibility: bool, + ) { + // For backwards compatibility, unconstrained might come before visibility. + // We'll remember this but put it after the visibility. + let unconstrained = if self.is_at_keyword(Keyword::Unconstrained) { + self.bump(); + self.skip_comments_and_whitespace(); + true + } else { + false + }; + + if skip_visibility { + // The intention here is to format the visibility into a temporary buffer that is discarded + self.chunk_formatter().chunk(|formatter| { + formatter.format_item_visibility(visibility); + }); + } else { + self.format_item_visibility(visibility); + } + + if unconstrained { + self.write("unconstrained "); + } else if self.is_at_keyword(Keyword::Unconstrained) { + self.write_keyword(Keyword::Unconstrained); + self.write_space(); + } + + if self.is_at_keyword(Keyword::Comptime) { + self.write_keyword(Keyword::Comptime); + self.write_space(); + } + } + + pub(super) fn format_function_parameters( + &mut self, + parameters: Vec, + group: &mut ChunkGroup, + ) { + self.chunk_formatter().format_items_separated_by_comma( + parameters, + false, // force trailing comma + false, // surround with spaces + group, + |formatter, param, group| { + group.text(formatter.chunk(|formatter| { + formatter.format_function_param(param); + })); + }, + ); + } + + fn format_function_param(&mut self, param: Param) { + self.format_pattern(param.pattern); + self.skip_comments_and_whitespace(); + + // There might not be a colon if the parameter is self + if self.is_at(Token::Colon) { + self.write_token(Token::Colon); + self.write_space(); + self.format_visibility(param.visibility); + self.format_type(param.typ); + } + } + + /// Returns whether the left brace of semicolon was written + /// (we don't write it when there's a comment before those tokens) + pub(super) fn format_function_right_paren_until_left_brace_or_semicolon( + &mut self, + return_type: FunctionReturnType, + visibility: Visibility, + has_where_clause: bool, + has_parameters: bool, + semicolon: bool, + mut group: ChunkGroup, + ) { + let mut chunk_formatter = self.chunk_formatter(); + + group.text(chunk_formatter.chunk(|formatter| { + formatter.write_right_paren(); + formatter.format_function_return_type(return_type, visibility); + })); + + // The following code is a bit long because it takes into account three scenarios: + // + // 1. + // fn foo() -> Field {} + // + // 2. + // fn foo() -> Field // comment + // {} + // + // 3. + // fn foo() -> Field + // // comment + // {} + // + // We want to preserve the above formatting when there are trailing comments, + // possibly considering a trailing comment in the same line to count towards the + // maximum width of the line. + // + // For that, we take the comment chunk and depending on whether it has leading newlines + // or if it even exists we take different paths. + let comment_chunk = chunk_formatter.skip_comments_and_whitespace_chunk(); + let comment_chunk = TextChunk::new(comment_chunk.string.trim_end().to_string()); + + let comment_starts_with_newline = comment_chunk.string.trim_matches(' ').starts_with('\n'); + if comment_starts_with_newline { + // After the return type we found a newline and a comment. We want to format the group + // right away, then keep formatting everything else (at that point there's no need to + // use chunks anymore). + self.format_chunk_group(group); + + let mut comment_group = ChunkGroup::new(); + comment_group.text(comment_chunk); + self.format_chunk_group(comment_group); + self.write_line(); + + // If there's no where clause the left brace goes on the same line as the function signature + if !has_where_clause { + self.skip_stray_where_keyword(); + + if semicolon { + self.write_semicolon(); + } else { + self.write_left_brace(); + } + } + return; + } + + let wrote_comment = !comment_chunk.string.trim().is_empty(); + group.text(comment_chunk); + + // If there's no where clause the left brace goes on the same line as the function signature + if !has_where_clause { + group.text(chunk_formatter.chunk(|formatter| { + formatter.skip_stray_where_keyword(); + })); + } + + if !has_where_clause && !wrote_comment { + if semicolon { + group.semicolon(&mut chunk_formatter); + } else { + group.text(chunk_formatter.chunk(|formatter| { + formatter.write_space(); + formatter.write_left_brace(); + })); + } + } + + if has_parameters { + self.format_chunk_group(group); + } else { + self.format_chunk_group_in_one_line(group); + } + + if wrote_comment { + self.write_line(); + if semicolon { + self.write_semicolon(); + } else { + self.write_left_brace(); + } + } + } + + fn skip_stray_where_keyword(&mut self) { + // There might still be a where keyword that we'll remove + if self.is_at_keyword(Keyword::Where) { + self.bump(); + self.skip_comments_and_whitespace(); + } + } + + fn format_function_return_type( + &mut self, + return_type: FunctionReturnType, + visibility: Visibility, + ) { + match return_type { + FunctionReturnType::Default(..) => (), + FunctionReturnType::Ty(typ) => { + self.write_space(); + self.write_token(Token::Arrow); + self.write_space(); + self.format_visibility(visibility); + self.format_type(typ); + } + } + } + + pub(super) fn format_function_body(&mut self, body: BlockExpression) { + let mut group = ChunkGroup::new(); + self.chunk_formatter().format_block_expression_contents( + body, true, // force multiple newlines + &mut group, + ); + self.format_chunk_group(group); + } +} + +#[cfg(test)] +mod tests { + use crate::{assert_format, assert_format_with_max_width}; + + #[test] + fn format_simple_function() { + let src = "mod moo { + /// hello +#[attr] pub fn foo ( ) { } }"; + let expected = "mod moo { + /// hello + #[attr] + pub fn foo() {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_args() { + let src = "fn foo ( x: i32 , y:i32 , ) { } "; + let expected = "fn foo(x: i32, y: i32) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_args_that_exceed_max_width() { + let src = "fn foo ( this_is_long: i32 , like_really_long:i32 , ) { } "; + let expected = "fn foo( + this_is_long: i32, + like_really_long: i32, +) {}\n"; + assert_format_with_max_width(src, expected, 40); + } + + #[test] + fn format_function_with_modifiers() { + let src = "pub unconstrained comptime fn foo ( ) { }"; + let expected = "pub unconstrained comptime fn foo() {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_unconstrained_before_pub() { + let src = "unconstrained pub fn foo ( ) { }"; + let expected = "pub unconstrained fn foo() {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_generics() { + let src = "fn foo < A, B, >( ) { }"; + let expected = "fn foo() {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_return_type() { + let src = "fn foo( ) -> Field { }"; + let expected = "fn foo() -> Field {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_parameter_pub_visibility() { + let src = "fn foo( x : pub u8 ) { }"; + let expected = "fn foo(x: pub u8) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_parameter_calldata_visibility() { + let src = "fn foo( x : call_data ( 1 ) u8 ) { }"; + let expected = "fn foo(x: call_data(1) u8) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_parameter_return_data_visibility() { + let src = "fn foo( x : return_data u8 ) { }"; + let expected = "fn foo(x: return_data u8) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_return_visibility() { + let src = "fn foo( ) -> pub Field { }"; + let expected = "fn foo() -> pub Field {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_empty_where_clause() { + let src = "mod foo { fn foo( ) where { } } "; + let expected = "mod foo { + fn foo() {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_where_clause() { + let src = "mod foo { fn foo( ) where T : Foo , U : Bar { } } "; + let expected = "mod foo { + fn foo() + where + T: Foo, + U: Bar, + {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_where_clause_multiple_bounds() { + let src = "mod foo { fn foo( ) where T : Foo+Bar , U : Baz + Qux { } } "; + let expected = "mod foo { + fn foo() + where + T: Foo + Bar, + U: Baz + Qux, + {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_body() { + let src = "fn main() { 1; 2; 3 }"; + let expected = "fn main() { + 1; + 2; + 3 +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_body_newlines() { + let src = "fn main() { + + 1; + + 2; + + 3 + + }"; + let expected = "fn main() { + 1; + + 2; + + 3 +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_body_one_expr() { + let src = "mod moo { fn main() { 1 } }"; + let expected = "mod moo { + fn main() { + 1 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_empty_body_multiple_lines() { + let src = "fn foo() { + + }"; + let expected = "fn foo() {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_trailing_comment_in_same_line_before_left_brace() { + let src = "fn foo(x: Field) // comment + { + }"; + let expected = "fn foo(x: Field) // comment +{} +"; + assert_format(src, expected); + } + + #[test] + fn format_function_with_trailing_comment_in_separate_line_before_left_brace() { + let src = "fn foo(x: Field) + // comment + { + }"; + let expected = "fn foo(x: Field) +// comment +{} +"; + assert_format(src, expected); + } + + #[test] + fn format_long_function_signature_no_parameters() { + let src = "fn foo() -> Field {}"; + let expected = "fn foo() -> Field {}\n"; + assert_format_with_max_width(src, expected, 15); + } + + #[test] + fn does_not_format_function_if_there_is_a_directive_not_to() { + let src = "// noir-fmt:ignore +fn foo() { let x = 1 ; + } + +fn bar() { let y = 2 ; + } + +// noir-fmt:ignore +fn baz() { let z = 3 ; + } + +"; + let expected = "// noir-fmt:ignore +fn foo() { let x = 1 ; + } + +fn bar() { + let y = 2; +} + +// noir-fmt:ignore +fn baz() { let z = 3 ; + } + +"; + assert_format(src, expected); + } + + #[test] + fn comment_in_body_respects_newlines() { + let src = "fn foo() { + let x = 1; + + // comment + + let y = 2; +} +"; + let expected = src; + assert_format(src, expected); + } + + #[test] + fn final_comment_in_body_respects_newlines() { + let src = "fn foo() { + let x = 1; + + let y = 2; + + // comment +} +"; + let expected = src; + assert_format(src, expected); + } + + #[test] + fn initial_comment_in_body_respects_newlines() { + let src = "fn foo() { + // comment + + let x = 1; + + let y = 2; +} +"; + let expected = src; + assert_format(src, expected); + } + + #[test] + fn keeps_newlines_between_comments_no_statements() { + let src = "fn foo() { + // foo + + // bar + + // baz +} +"; + let expected = src; + assert_format(src, expected); + } + + #[test] + fn keeps_newlines_between_comments_one_statement() { + let src = "fn foo() { + let x = 1; + + // foo + + // bar + + // baz +} +"; + let expected = src; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/generics.rs b/tooling/nargo_fmt/src/formatter/generics.rs new file mode 100644 index 00000000000..4ee5a743942 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/generics.rs @@ -0,0 +1,96 @@ +use noirc_frontend::{ + ast::{GenericTypeArgKind, GenericTypeArgs, UnresolvedGeneric}, + token::{Keyword, Token}, +}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_generics(&mut self, generics: Vec) { + self.skip_comments_and_whitespace(); + + if self.token != Token::Less { + return; + } + + self.write_token(Token::Less); + for (index, generic) in generics.into_iter().enumerate() { + if index > 0 { + self.write_comma(); + self.write_space(); + } + self.format_generic(generic); + } + self.skip_comments_and_whitespace(); + + // Trailing comma + if self.is_at(Token::Comma) { + self.bump(); + } + + self.write_token(Token::Greater); + } + + fn format_generic(&mut self, generic: UnresolvedGeneric) { + self.skip_comments_and_whitespace(); + match generic { + UnresolvedGeneric::Variable(ident) => { + self.write_identifier(ident); + } + UnresolvedGeneric::Numeric { ident, typ } => { + self.write_keyword(Keyword::Let); + self.write_space(); + self.write_identifier(ident); + self.write_token(Token::Colon); + self.write_space(); + self.format_type(typ); + } + UnresolvedGeneric::Resolved(..) => { + unreachable!("Resolved generics should not be present in the AST") + } + } + } + + pub(super) fn format_generic_type_args(&mut self, mut generics: GenericTypeArgs) { + self.skip_comments_and_whitespace(); + if self.token != Token::Less { + return; + } + + self.write_token(Token::Less); + + for (index, kind) in generics.kinds.into_iter().enumerate() { + self.skip_comments_and_whitespace(); + + if index > 0 { + self.write_token(Token::Comma); + self.write_space(); + } + + match kind { + GenericTypeArgKind::Ordered => { + let typ = generics.ordered_args.remove(0); + self.format_type(typ); + } + GenericTypeArgKind::Named => { + let (name, typ) = generics.named_args.remove(0); + self.write_identifier(name); + self.write_space(); + self.write_token(Token::Assign); + self.write_space(); + self.format_type(typ); + } + } + } + + self.skip_comments_and_whitespace(); + + // Don't include a trailing comma if there is one + if self.is_at(Token::Comma) { + self.bump(); + self.skip_comments_and_whitespace(); + } + + self.write_token(Token::Greater); + } +} diff --git a/tooling/nargo_fmt/src/formatter/global.rs b/tooling/nargo_fmt/src/formatter/global.rs new file mode 100644 index 00000000000..783629c8e32 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/global.rs @@ -0,0 +1,102 @@ +use noirc_frontend::{ + ast::{ItemVisibility, LetStatement, Pattern}, + token::Keyword, +}; + +use super::Formatter; +use crate::chunks::{ChunkFormatter, ChunkGroup}; + +impl<'a> Formatter<'a> { + pub(super) fn format_global( + &mut self, + let_statement: LetStatement, + visibility: ItemVisibility, + ) { + let group = self.chunk_formatter().format_global(let_statement, visibility); + self.write_indentation(); + self.format_chunk_group(group); + } +} + +impl<'a, 'b> ChunkFormatter<'a, 'b> { + pub(super) fn format_global( + &mut self, + let_statement: LetStatement, + visibility: ItemVisibility, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.text(self.chunk(|formatter| { + formatter.format_item_visibility(visibility); + })); + + if let_statement.comptime { + group.text(self.chunk(|formatter| { + formatter.write_keyword(Keyword::Comptime); + formatter.write_space(); + })); + } + + let pattern = let_statement.pattern; + let pattern = match pattern { + Pattern::Identifier(..) => pattern, + Pattern::Mutable(pattern, _span, _) => { + // `mut global x` is represented in the AST with a mutable pattern. + // A mutable pattern would be `mut x` but here we have `mut global x`, + // so in that case we write `mut` now, then the pattern we'll write doesn't + // have the `mut` part. + group.text(self.chunk(|formatter| { + formatter.write_keyword(Keyword::Mut); + formatter.write_space(); + })); + + *pattern + } + Pattern::Tuple(..) | Pattern::Struct(..) | Pattern::Interned(..) => { + unreachable!("Global pattern cannot be a tuple, struct or interned") + } + }; + + group.group(self.format_let_or_global( + Keyword::Global, + pattern, + let_statement.r#type, + Some(let_statement.expression), + Vec::new(), // Attributes + )); + + group + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + #[test] + fn format_global_without_type() { + let src = " pub global x = 1 ; "; + let expected = "pub global x = 1;\n"; + assert_format(src, expected); + } + + #[test] + fn format_global_with_type() { + let src = " pub global x : Field = 1 ; "; + let expected = "pub global x: Field = 1;\n"; + assert_format(src, expected); + } + + #[test] + fn format_comptime_global() { + let src = " pub comptime global x : Field = 1 ; "; + let expected = "pub comptime global x: Field = 1;\n"; + assert_format(src, expected); + } + + #[test] + fn format_comptime_mut_global() { + let src = " pub comptime mut global x : Field = 1 ; "; + let expected = "pub comptime mut global x: Field = 1;\n"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/impls.rs b/tooling/nargo_fmt/src/formatter/impls.rs new file mode 100644 index 00000000000..71548dd5efa --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/impls.rs @@ -0,0 +1,125 @@ +use noirc_frontend::{ast::TypeImpl, token::Keyword}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_impl(&mut self, type_impl: TypeImpl) { + let has_where_clause = !type_impl.where_clause.is_empty(); + + self.write_indentation(); + self.write_keyword(Keyword::Impl); + self.format_generics(type_impl.generics); + self.write_space(); + self.format_type(type_impl.object_type); + + if has_where_clause { + self.format_where_clause( + type_impl.where_clause, + true, // write trailing comma and newline + ); + } else { + self.write_space(); + } + self.write_left_brace(); + + if type_impl.methods.is_empty() { + self.format_empty_block_contents(); + } else { + self.increase_indentation(); + self.write_line(); + + for (index, (documented_method, _span)) in type_impl.methods.into_iter().enumerate() { + if index > 0 { + self.write_line(); + } + + let doc_comments = documented_method.doc_comments; + let method = documented_method.item; + if !doc_comments.is_empty() { + self.format_outer_doc_comments(); + } + self.format_function( + method, false, // skip visibility + ); + } + + self.skip_comments_and_whitespace(); + self.decrease_indentation(); + self.write_line(); + self.write_indentation(); + } + + self.write_right_brace(); + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + #[test] + fn format_empty_impl() { + let src = " mod moo { impl Foo { } }"; + let expected = "mod moo { + impl Foo {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_impl_with_generics() { + let src = " mod moo { impl < A, B > Foo < A, B > { } }"; + let expected = "mod moo { + impl Foo {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_impl_with_where_clause() { + let src = " mod moo { impl Foo where A: B { } }"; + let expected = "mod moo { + impl Foo + where + A: B, + {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_impl_with_functions() { + let src = " mod moo { impl Foo { +/// hello +pub fn foo () { 1 } + +/// world +pub ( crate ) fn bar () { + } + +fn one(self) {} +fn two(mut self) {} +fn three(&mut self) {} + } }"; + let expected = "mod moo { + impl Foo { + /// hello + pub fn foo() { + 1 + } + + /// world + pub(crate) fn bar() {} + + fn one(self) {} + fn two(mut self) {} + fn three(&mut self) {} + } +} +"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/item.rs b/tooling/nargo_fmt/src/formatter/item.rs new file mode 100644 index 00000000000..3365e52ec29 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/item.rs @@ -0,0 +1,178 @@ +use noirc_frontend::{ + ast::{ItemVisibility, UseTree}, + hir::resolution::errors::Span, + parser::{Item, ItemKind}, +}; + +use crate::config::ImportsGranularity; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_items(&mut self, mut items: Vec, mut ignore_next: bool) { + // Reverse the items because we'll be processing them one by one, and it's a bit + // more efficient to pop than to shift. + items.reverse(); + + while !items.is_empty() { + // Format the next import group, if there is one. + let import_group = self.next_import_group(&mut items); + if let Some(import_group) = import_group { + self.merge_and_format_imports(import_group.imports, import_group.visibility); + self.skip_past_span_end_without_formatting(import_group.span_end); + self.write_line(); + ignore_next = self.ignore_next; + + // Continue from the top because the next thing that comes might be another import group + continue; + } + + if let Some(item) = items.pop() { + self.format_item(item, ignore_next); + self.write_line(); + ignore_next = self.ignore_next; + } else { + break; + } + } + } + + pub(super) fn format_item(&mut self, item: Item, mut ignore_next: bool) { + self.skip_comments_and_whitespace(); + + ignore_next |= self.ignore_next; + + if !item.doc_comments.is_empty() { + self.format_outer_doc_comments(); + self.skip_comments_and_whitespace(); + } + + ignore_next |= self.ignore_next; + + if ignore_next { + self.write_and_skip_span_without_formatting(item.span); + return; + } + + match item.kind { + ItemKind::Import(use_tree, item_visibility) => { + self.format_import(use_tree, item_visibility); + } + ItemKind::Function(noir_function) => self.format_function( + noir_function, + false, // skip visibility + ), + ItemKind::Struct(noir_struct) => self.format_struct(noir_struct), + ItemKind::Trait(noir_trait) => self.format_trait(noir_trait), + ItemKind::TraitImpl(noir_trait_impl) => self.format_trait_impl(noir_trait_impl), + ItemKind::Impl(type_impl) => self.format_impl(type_impl), + ItemKind::TypeAlias(noir_type_alias) => self.format_type_alias(noir_type_alias), + ItemKind::Global(let_statement, visibility) => { + self.format_global(let_statement, visibility); + } + ItemKind::ModuleDecl(module_declaration) => { + self.format_module_declaration(module_declaration); + } + ItemKind::Submodules(parsed_sub_module) => { + self.format_submodule(parsed_sub_module); + } + ItemKind::InnerAttribute(attribute) => self.format_secondary_attribute(attribute), + } + } + + /// Returns the next import group, if there's is one. + /// + /// An import group is one or more `use` statements that all have the same visibility, + /// as long as exactly one newline separates them, and as long as there are no comments + /// in the `use` statements or trailing comments in them. + /// + /// Each import group will be sorted and merged, if the configuration is set to do so. + fn next_import_group(&self, items: &mut Vec) -> Option { + if self.config.imports_granularity == ImportsGranularity::Preserve + && !self.config.reorder_imports + { + return None; + } + + let mut imports = Vec::new(); + + let item = items.last()?; + if self.span_has_comments(item.span) { + return None; + } + + let ItemKind::Import(..) = item.kind else { + return None; + }; + + let item = items.pop().unwrap(); + let ItemKind::Import(use_tree, visibility) = item.kind else { + panic!("Expected import, got {:?}", item.kind); + }; + + imports.push(use_tree); + let mut span_end = item.span.end(); + + while let Some(item) = items.last() { + if self.span_is_import_group_separator(Span::from(span_end..item.span.start())) { + break; + } + + let next_item_start = if items.len() > 1 { + if let Some(next_item) = items.get(items.len() - 2) { + next_item.span.start() + } else { + self.source.len() as u32 + } + } else { + self.source.len() as u32 + }; + + if self.span_starts_with_trailing_comment(Span::from(item.span.end()..next_item_start)) + { + break; + } + + let ItemKind::Import(_, next_visibility) = &item.kind else { + break; + }; + + if visibility != *next_visibility { + break; + } + + let item = items.pop().unwrap(); + let ItemKind::Import(use_tree, _) = item.kind else { + panic!("Expected import, got {:?}", item.kind); + }; + imports.push(use_tree); + span_end = item.span.end(); + } + + Some(ImportGroup { imports, visibility, span_end }) + } + + fn span_has_comments(&self, span: Span) -> bool { + let slice = &self.source[span.start() as usize..span.end() as usize]; + slice.contains("/*") || slice.contains("//") + } + + fn span_starts_with_trailing_comment(&self, span: Span) -> bool { + let slice = &self.source[span.start() as usize..span.end() as usize]; + slice.trim_start_matches(' ').starts_with("//") + } + + /// Returns true if there at most one newline in the given span and it contains no comments. + fn span_is_import_group_separator(&self, span: Span) -> bool { + let slice = &self.source[span.start() as usize..span.end() as usize]; + let number_of_newlines = slice.chars().filter(|char| *char == '\n').count(); + number_of_newlines > 1 || slice.contains("//") || slice.contains("/*") + } +} + +#[derive(Debug)] +struct ImportGroup { + imports: Vec, + visibility: ItemVisibility, + span_end: u32, +} diff --git a/tooling/nargo_fmt/src/formatter/lvalue.rs b/tooling/nargo_fmt/src/formatter/lvalue.rs new file mode 100644 index 00000000000..15fb7f5fa26 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/lvalue.rs @@ -0,0 +1,44 @@ +use noirc_frontend::{ast::LValue, token::Token}; + +use super::Formatter; +use crate::chunks::ChunkGroup; + +impl<'a> Formatter<'a> { + pub(super) fn format_lvalue(&mut self, lvalue: LValue) { + // Parenthesized l-values exist but are not represented in the AST + while let Token::LeftParen = self.token { + self.write_left_paren(); + } + + match lvalue { + LValue::Ident(ident) => self.write_identifier(ident), + LValue::MemberAccess { object, field_name, span: _ } => { + self.format_lvalue(*object); + self.write_token(Token::Dot); + self.write_identifier_or_integer(field_name); + } + LValue::Index { array, index, span: _ } => { + self.format_lvalue(*array); + self.write_left_bracket(); + let mut group = ChunkGroup::new(); + self.chunk_formatter().format_expression(index, &mut group); + self.format_chunk_group(group); + self.write_right_bracket(); + } + LValue::Dereference(lvalue, _span) => { + self.write_token(Token::Star); + self.format_lvalue(*lvalue); + } + LValue::Interned(..) => { + unreachable!("Should not be present in the AST") + } + } + + self.skip_comments_and_whitespace(); + + // Parenthesized l-values exist but are not represented in the AST + while let Token::RightParen = self.token { + self.write_right_paren(); + } + } +} diff --git a/tooling/nargo_fmt/src/formatter/module.rs b/tooling/nargo_fmt/src/formatter/module.rs new file mode 100644 index 00000000000..e07d22c7586 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/module.rs @@ -0,0 +1,140 @@ +use noirc_frontend::{ + ast::ModuleDeclaration, parser::ParsedSubModule, token::Keyword, ParsedModule, +}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_module_declaration(&mut self, module_declaration: ModuleDeclaration) { + self.format_secondary_attributes(module_declaration.outer_attributes); + self.write_indentation(); + self.format_item_visibility(module_declaration.visibility); + self.write_keyword(Keyword::Mod); + self.write_space(); + self.write_identifier(module_declaration.ident); + self.write_semicolon(); + } + + pub(super) fn format_submodule(&mut self, submodule: ParsedSubModule) { + self.format_secondary_attributes(submodule.outer_attributes); + self.write_indentation(); + self.format_item_visibility(submodule.visibility); + if submodule.is_contract { + self.write_keyword(Keyword::Contract); + } else { + self.write_keyword(Keyword::Mod); + } + self.write_space(); + self.write_identifier(submodule.name); + self.write_space(); + self.write_left_brace(); + if parsed_module_is_empty(&submodule.contents) { + self.format_empty_block_contents(); + } else { + self.increase_indentation(); + self.write_line(); + self.format_parsed_module(submodule.contents, self.ignore_next); + self.decrease_indentation(); + self.write_indentation(); + } + self.write_right_brace(); + } +} + +fn parsed_module_is_empty(parsed_module: &ParsedModule) -> bool { + parsed_module.inner_doc_comments.is_empty() && parsed_module.items.is_empty() +} + +#[cfg(test)] +mod tests { + use crate::{assert_format, assert_format_with_config, Config}; + + #[test] + fn format_module_declaration() { + let src = " mod foo ; "; + let expected = "mod foo;\n"; + assert_format(src, expected); + } + + #[test] + fn format_module_declaration_with_doc_comments() { + let src = " /// hello +/// world +mod foo ; "; + let expected = "/// hello +/// world +mod foo;\n"; + assert_format(src, expected); + } + + #[test] + fn format_module_declaration_with_pub_visibility() { + let src = " pub mod foo ;"; + let expected = "pub mod foo;\n"; + assert_format(src, expected); + } + + #[test] + fn format_module_declaration_with_pub_crate_visibility() { + let src = " pub ( crate ) mod foo ;"; + let expected = "pub(crate) mod foo;\n"; + assert_format(src, expected); + } + + #[test] + fn format_empty_submodule() { + let src = "mod foo { }"; + let expected = "mod foo {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_empty_submodule_2() { + let src = "mod foo { mod bar { + + } }"; + let expected = "mod foo { + mod bar {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_subcontract() { + let src = "contract foo { }"; + let expected = "contract foo {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_multiple_modules() { + let src = " mod foo { +// hello +mod bar { +// world +} +} "; + let expected = "mod foo { + // hello + mod bar { + // world + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_submodule_with_configurable_tab_spaces() { + let src = " mod foo { + mod bar ; + }"; + let expected = "mod foo { + mod bar; +} +"; + let config = Config { tab_spaces: 2, ..Config::default() }; + assert_format_with_config(src, expected, config); + } +} diff --git a/tooling/nargo_fmt/src/formatter/path.rs b/tooling/nargo_fmt/src/formatter/path.rs new file mode 100644 index 00000000000..2a46467bf72 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/path.rs @@ -0,0 +1,59 @@ +use noirc_frontend::{ + ast::{Path, PathKind, UnresolvedType}, + token::{Keyword, Token}, +}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_path(&mut self, path: Path) { + self.skip_comments_and_whitespace(); + + match path.kind { + PathKind::Plain => (), + PathKind::Crate => { + self.write_keyword(Keyword::Crate); + self.write_token(Token::DoubleColon); + } + PathKind::Dep => { + self.write_keyword(Keyword::Dep); + self.write_token(Token::DoubleColon); + } + PathKind::Super => { + self.write_keyword(Keyword::Super); + self.write_token(Token::DoubleColon); + } + } + + for (index, segment) in path.segments.into_iter().enumerate() { + if index > 0 { + self.write_token(Token::DoubleColon); + } + self.write_identifier(segment.ident); + + if let Some(generics) = segment.generics { + self.format_turbofish(generics); + } + } + } + + pub(super) fn format_turbofish(&mut self, generics: Vec) { + self.write_token(Token::DoubleColon); + self.write_token(Token::Less); + for (index, typ) in generics.into_iter().enumerate() { + if index > 0 { + self.write_comma(); + self.write_space(); + } + self.format_type(typ); + } + + // Skip trailing comma, if any + self.skip_comments_and_whitespace(); + if self.is_at(Token::Comma) { + self.bump(); + } + + self.write_token(Token::Greater); + } +} diff --git a/tooling/nargo_fmt/src/formatter/pattern.rs b/tooling/nargo_fmt/src/formatter/pattern.rs new file mode 100644 index 00000000000..9a76612109b --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/pattern.rs @@ -0,0 +1,162 @@ +use noirc_frontend::{ + ast::{Ident, Pattern}, + token::{Keyword, Token}, +}; + +use super::Formatter; +use crate::chunks::ChunkGroup; + +impl<'a> Formatter<'a> { + pub(super) fn format_pattern(&mut self, pattern: Pattern) { + self.skip_comments_and_whitespace(); + + // Special case: `&mut self` (this is reflected in the param type, not the pattern) + if self.is_at(Token::Ampersand) { + self.write_token(Token::Ampersand); + self.write_keyword(Keyword::Mut); + self.write_space(); + } + + match pattern { + Pattern::Identifier(ident) => self.write_identifier(ident), + Pattern::Mutable(pattern, _span, _) => { + self.write_keyword(Keyword::Mut); + self.write_space(); + self.format_pattern(*pattern); + } + Pattern::Tuple(patterns, _span) => { + let patterns_len = patterns.len(); + + self.write_left_paren(); + for (index, pattern) in patterns.into_iter().enumerate() { + if index > 0 { + self.write_comma(); + self.write_space(); + } + self.format_pattern(pattern); + } + + // Check for trailing comma + self.skip_comments_and_whitespace(); + if self.is_at(Token::Comma) { + if patterns_len == 1 { + self.write_comma(); + } else { + self.bump(); + } + } + + self.write_right_paren(); + } + Pattern::Struct(path, fields, _span) => { + self.format_path(path); + self.write_space(); + self.write_left_brace(); + if fields.is_empty() { + self.format_empty_block_contents(); + } else { + let mut group = ChunkGroup::new(); + self.chunk_formatter().format_items_separated_by_comma( + fields, + false, // force trailing comma, + true, // surround with spaces + &mut group, + |formatter, (name, pattern), chunks| { + let is_identifier_pattern = is_identifier_pattern(&pattern, &name); + + chunks.text(formatter.chunk(|formatter| { + formatter.write_identifier(name); + formatter.skip_comments_and_whitespace(); + })); + if formatter.is_at(Token::Colon) { + let value_chunk = formatter.chunk(|formatter| { + formatter.write_token(Token::Colon); + formatter.write_space(); + formatter.format_pattern(pattern); + }); + if !is_identifier_pattern { + chunks.text(value_chunk); + } + } + }, + ); + self.format_chunk_group(group); + } + + self.write_right_brace(); + } + Pattern::Interned(..) => { + unreachable!("Should not be present in the AST") + } + } + } +} + +fn is_identifier_pattern(pattern: &Pattern, ident: &Ident) -> bool { + if let Pattern::Identifier(pattern_ident) = pattern { + pattern_ident == ident + } else { + false + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + #[test] + fn format_identifier_pattern() { + let src = "fn foo( x : i32) {}"; + let expected = "fn foo(x: i32) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_mutable_pattern() { + let src = "fn foo( mut x : i32) {}"; + let expected = "fn foo(mut x: i32) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_tuple_pattern_no_trailing_comma() { + let src = "fn foo( ( x , y ) : i32) {}"; + let expected = "fn foo((x, y): i32) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_tuple_pattern_trailing_comma() { + let src = "fn foo( ( x , y , ) : i32) {}"; + let expected = "fn foo((x, y): i32) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_tuple_pattern_one_element() { + let src = "fn foo( ( x , ) : i32) {}"; + let expected = "fn foo((x,): i32) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_struct_pattern_empty() { + let src = "fn foo( Foo { } : i32) {}"; + let expected = "fn foo(Foo {}: i32) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_struct_pattern() { + let src = "fn foo( Foo { x : one , y : two } : i32) {}"; + let expected = "fn foo(Foo { x: one, y: two }: i32) {}\n"; + assert_format(src, expected); + } + + #[test] + fn format_struct_pattern_no_pattern() { + let src = "fn foo( Foo { x , y : y } : i32) {}"; + let expected = "fn foo(Foo { x, y }: i32) {}\n"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/statement.rs b/tooling/nargo_fmt/src/formatter/statement.rs new file mode 100644 index 00000000000..9e3ea652ec6 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/statement.rs @@ -0,0 +1,752 @@ +use noirc_frontend::{ + ast::{ + AssignStatement, ConstrainKind, ConstrainStatement, Expression, ExpressionKind, + ForLoopStatement, ForRange, LetStatement, Pattern, Statement, StatementKind, + UnresolvedType, UnresolvedTypeData, + }, + token::{Keyword, SecondaryAttribute, Token, TokenKind}, +}; + +use crate::chunks::{ChunkFormatter, ChunkGroup, GroupKind}; + +impl<'a, 'b> ChunkFormatter<'a, 'b> { + pub(super) fn format_statement( + &mut self, + statement: Statement, + group: &mut ChunkGroup, + mut ignore_next: bool, + ) { + // First skip any whitespace to avoid writing multiple lines + group.text(self.chunk(|formatter| { + formatter.skip_whitespace(); + })); + + // Now write any leading comment respecting multiple newlines after them + group.leading_comment(self.chunk(|formatter| { + // Doc comments for a let statement could come before a potential non-doc comment + if formatter.token.kind() == TokenKind::OuterDocComment { + formatter.format_outer_doc_comments(); + } + + formatter.skip_comments_and_whitespace_writing_multiple_lines_if_found(); + + // Or doc comments could come after a potential non-doc comment + if formatter.token.kind() == TokenKind::OuterDocComment { + formatter.format_outer_doc_comments(); + } + })); + + ignore_next |= self.ignore_next; + + if ignore_next { + group.text(self.chunk(|formatter| { + formatter.write_and_skip_span_without_formatting(statement.span); + })); + return; + } + + match statement.kind { + StatementKind::Let(let_statement) => { + group.group(self.format_let_statement(let_statement)); + } + StatementKind::Constrain(constrain_statement) => { + group.group(self.format_constrain_statement(constrain_statement)); + } + StatementKind::Expression(expression) => match expression.kind { + ExpressionKind::Block(block) => group.group(self.format_block_expression( + block, true, // force multiple lines + )), + ExpressionKind::Unsafe(block, _) => { + group.group(self.format_unsafe_expression( + block, true, // force multiple lines + )); + } + ExpressionKind::If(if_expression) => { + group.group(self.format_if_expression( + *if_expression, + true, // force multiple lines + )); + } + _ => self.format_expression(expression, group), + }, + StatementKind::Assign(assign_statement) => { + group.group(self.format_assign(assign_statement)); + } + StatementKind::For(for_loop_statement) => { + group.group(self.format_for_loop(for_loop_statement)); + } + StatementKind::Break => { + group.text(self.chunk(|formatter| { + formatter.write_keyword(Keyword::Break); + formatter.write_semicolon(); + })); + } + StatementKind::Continue => { + group.text(self.chunk(|formatter| { + formatter.write_keyword(Keyword::Continue); + formatter.write_semicolon(); + })); + } + StatementKind::Comptime(statement) => { + group.group(self.format_comptime_statement(*statement)); + } + StatementKind::Semi(expression) => { + group.group(self.format_semi_statement(expression)); + } + StatementKind::Interned(..) | StatementKind::Error => { + unreachable!("Should not be present in the AST") + } + } + } + + fn format_let_statement(&mut self, let_statement: LetStatement) -> ChunkGroup { + self.format_let_or_global( + Keyword::Let, + let_statement.pattern, + let_statement.r#type, + Some(let_statement.expression), + let_statement.attributes, + ) + } + + pub(super) fn format_let_or_global( + &mut self, + keyword: Keyword, + pattern: Pattern, + typ: UnresolvedType, + value: Option, + attributes: Vec, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + + group.text(self.chunk(|formatter| { + formatter.format_secondary_attributes(attributes); + formatter.write_keyword(keyword); + formatter.write_space(); + formatter.format_pattern(pattern); + if typ.typ != UnresolvedTypeData::Unspecified { + formatter.write_token(Token::Colon); + formatter.write_space(); + formatter.format_type(typ); + } + })); + + if let Some(value) = value { + group.text(self.chunk(|formatter| { + formatter.write_space(); + formatter.write_token(Token::Assign); + formatter.write_space(); + })); + + let mut value_group = ChunkGroup::new(); + value_group.kind = GroupKind::AssignValue; + self.format_expression(value, &mut value_group); + value_group.semicolon(self); + group.group(value_group); + } else { + group.semicolon(self); + } + + group + } + + fn format_constrain_statement( + &mut self, + constrain_statement: ConstrainStatement, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + + let keyword = match constrain_statement.kind { + ConstrainKind::Assert => Keyword::Assert, + ConstrainKind::AssertEq => Keyword::AssertEq, + ConstrainKind::Constrain => { + unreachable!("constrain always produces an error, and the formatter doesn't run when there are errors") + } + }; + + group.text(self.chunk(|formatter| { + formatter.write_keyword(keyword); + formatter.write_left_paren(); + })); + + group.kind = GroupKind::ExpressionList { + prefix_width: group.width(), + expressions_count: constrain_statement.arguments.len(), + }; + + self.format_expressions_separated_by_comma( + constrain_statement.arguments, + false, // force trailing comma + &mut group, + ); + + group.text(self.chunk(|formatter| { + formatter.write_right_paren(); + formatter.write_semicolon(); + })); + + group + } + + fn format_assign(&mut self, assign_statement: AssignStatement) -> ChunkGroup { + let mut group = ChunkGroup::new(); + let mut is_op_assign = false; + + group.text(self.chunk(|formatter| { + formatter.format_lvalue(assign_statement.lvalue); + formatter.write_space(); + if formatter.is_at(Token::Assign) { + formatter.write_token(Token::Assign); + } else { + // This is something like `x += 1`, which is parsed as an + // Assign with an InfixExpression as its right-hand side: `x = x + 1`. + // There will always be two tokens here, like `+ =` or `> >=`. + formatter.write_current_token(); + formatter.bump(); + formatter.skip_comments_and_whitespace(); + formatter.write_current_token(); + formatter.bump(); + + is_op_assign = true; + } + formatter.write_space(); + })); + + let mut value_group = ChunkGroup::new(); + value_group.kind = GroupKind::AssignValue; + + if is_op_assign { + let ExpressionKind::Infix(infix) = assign_statement.expression.kind else { + panic!("Expected an infix expression for op assign"); + }; + self.format_expression(infix.rhs, &mut value_group); + } else { + self.format_expression(assign_statement.expression, &mut value_group); + } + value_group.semicolon(self); + group.group(value_group); + + group + } + + fn format_for_loop(&mut self, for_loop: ForLoopStatement) -> ChunkGroup { + let mut group = ChunkGroup::new(); + + group.text(self.chunk(|formatter| { + formatter.write_keyword(Keyword::For); + formatter.write_space(); + formatter.write_identifier(for_loop.identifier); + formatter.write_space(); + formatter.write_keyword(Keyword::In); + formatter.write_space(); + })); + + match for_loop.range { + ForRange::Range(for_bounds) => { + self.format_expression(for_bounds.start, &mut group); + group.text(self.chunk(|formatter| { + formatter.skip_comments_and_whitespace(); + formatter.write_current_token(); + formatter.bump(); + })); + self.format_expression(for_bounds.end, &mut group); + } + ForRange::Array(expression) => { + self.format_expression(expression, &mut group); + } + } + + group.space(self); + + let ExpressionKind::Block(block) = for_loop.block.kind else { + panic!("Expected a block expression for for loop body"); + }; + + group.group(self.format_block_expression( + block, true, // force multiple lines + )); + + // If there's a trailing semicolon, remove it + group.text(self.chunk(|formatter| { + formatter.skip_whitespace_if_it_is_not_a_newline(); + if formatter.is_at(Token::Semicolon) { + formatter.bump(); + } + })); + + group + } + + fn format_comptime_statement(&mut self, statement: Statement) -> ChunkGroup { + let mut group = ChunkGroup::new(); + + // A comptime statement can be a let, a block or a for. + // We always want to force multiple lines except for let. + group.force_multiple_lines = !matches!(statement.kind, StatementKind::Let(..)); + + group.text(self.chunk(|formatter| { + formatter.write_keyword(Keyword::Comptime); + formatter.write_space(); + })); + self.format_statement( + statement, &mut group, false, // ignore next + ); + group + } + + fn format_semi_statement(&mut self, expression: Expression) -> ChunkGroup { + let mut group = ChunkGroup::new(); + + self.format_expression(expression, &mut group); + + group.text(self.chunk(|formatter| { + formatter.skip_comments_and_whitespace(); + })); + + group.semicolon(self); + + group + } +} + +#[cfg(test)] +mod tests { + use crate::{assert_format, assert_format_with_max_width}; + + #[test] + fn format_expression_statement() { + let src = " fn foo() { 1 } "; + let expected = "fn foo() { + 1 +} +"; + assert_format(src, expected); + } + + #[test] + fn format_semi_statement() { + let src = " fn foo() { 1 ; } "; + let expected = "fn foo() { + 1; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_break_statement() { + let src = " fn foo() { break ; } "; + let expected = "fn foo() { + break; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_continue_statement() { + let src = " fn foo() { continue ; } "; + let expected = "fn foo() { + continue; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_let_statement_no_type() { + let src = " fn foo() { let x = 1 ; } "; + let expected = "fn foo() { + let x = 1; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_let_statement_with_type() { + let src = " fn foo() { let x : Field = 1 ; } "; + let expected = "fn foo() { + let x: Field = 1; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_let_statement_with_attribute() { + let src = " fn foo() { #[allow(unused_variables)] let x = 1 ; } "; + let expected = "fn foo() { + #[allow(unused_variables)] + let x = 1; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_let_statement_with_unsafe() { + let src = " fn foo() { + /// Safety: some doc + let x = unsafe { 1 } ; } "; + let expected = "fn foo() { + /// Safety: some doc + let x = unsafe { 1 }; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_let_statement_with_unsafe_and_comment_before_it() { + let src = " fn foo() { + // Some comment + /// Safety: some doc + let x = unsafe { 1 } ; } "; + let expected = "fn foo() { + // Some comment + /// Safety: some doc + let x = unsafe { 1 }; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_assign() { + let src = " fn foo() { x = 2 ; } "; + let expected = "fn foo() { + x = 2; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_assign_to_member() { + let src = " fn foo() { x . y = 2 ; } "; + let expected = "fn foo() { + x.y = 2; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_assign_to_tuple_member() { + let src = " fn foo() { x . 0 = 2 ; } "; + let expected = "fn foo() { + x.0 = 2; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_assign_to_index() { + let src = " fn foo() { x [ y ] = 2 ; } "; + let expected = "fn foo() { + x[y] = 2; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_assign_to_dereference() { + let src = " fn foo() { * x = 2 ; } "; + let expected = "fn foo() { + *x = 2; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_assign_with_parentheses() { + let src = " fn foo() { ( array[0] )[1] = 2; } "; + let expected = "fn foo() { + (array[0])[1] = 2; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_op_assign() { + let src = " fn foo() { x + = 2 ; } "; + let expected = "fn foo() { + x += 2; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_shift_right_assign() { + let src = " fn foo() { x >>= 2 ; } "; + let expected = "fn foo() { + x >>= 2; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_comptime_let_statement() { + let src = " fn foo() { comptime let x = 1 ; } "; + let expected = "fn foo() { + comptime let x = 1; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_block_statement() { + let src = " fn foo() { { } } "; + let expected = "fn foo() { + {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_block_statement() { + let src = " fn foo() { { 1 ; 2 } } "; + let expected = "fn foo() { + { + 1; + 2 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_unsafe_statement() { + let src = " fn foo() { unsafe { + 1 } } "; + let expected = "fn foo() { + unsafe { + 1 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_comptime_statement_one_statement() { + let src = " fn foo() { comptime { 1 } } "; + let expected = "fn foo() { + comptime { + 1 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_comptime_block_statement() { + let src = " fn foo() { comptime { 1 ; 2 } } "; + let expected = "fn foo() { + comptime { + 1; + 2 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_for_array() { + let src = " fn foo() { for x in array { 1 } } "; + let expected = "fn foo() { + for x in array { + 1 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_for_array_trailing_semicolon() { + let src = " fn foo() { for x in array { 1 } ; } "; + let expected = "fn foo() { + for x in array { + 1 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_for_range_exclusive() { + let src = " fn foo() { for x in 1 .. 10 { 1 } } "; + let expected = "fn foo() { + for x in 1..10 { + 1 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_for_range_inclusive() { + let src = " fn foo() { for x in 1 ..= 10 { 1 } } "; + let expected = "fn foo() { + for x in 1..=10 { + 1 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_two_for_separated_by_multiple_lines() { + let src = " fn foo() { for x in array { 1 } + + for x in array { 1 } + + } "; + let expected = "fn foo() { + for x in array { + 1 + } + + for x in array { + 1 + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_assert() { + let src = r#" fn foo() { assert ( true , "hello" ) ; } "#; + let expected = r#"fn foo() { + assert(true, "hello"); +} +"#; + assert_format(src, expected); + } + + #[test] + fn format_assert_eq() { + let src = r#" fn foo() { assert ( 1 , 2 , "hello" ) ; } "#; + let expected = r#"fn foo() { + assert(1, 2, "hello"); +} +"#; + assert_format(src, expected); + } + + #[test] + fn format_if_statement() { + let src = r#" fn foo() { if 1 { 2 } } "#; + let expected = r#"fn foo() { + if 1 { + 2 + } +} +"#; + assert_format(src, expected); + } + + #[test] + fn does_not_format_statement_if_there_is_a_directive_not_to() { + let src = "fn foo() { + // noir-fmt:ignore + let x = + 1 ; + + let y = + 2 ; + + // noir-fmt:ignore + let z = + 3 ; +}\n"; + let expected = "fn foo() { + // noir-fmt:ignore + let x = + 1 ; + + let y = 2; + + // noir-fmt:ignore + let z = + 3 ; +}\n"; + assert_format(src, expected); + } + + #[test] + fn attaches_semicolon_to_last_group_in_let_statement() { + let src = "fn foo() { + let x = foo(1, 2); +} +"; + let expected = "fn foo() { + let x = + foo(1, 2); +} +"; + assert_format_with_max_width(src, expected, " let x = foo(1, 2);".len() - 1); + } + + #[test] + fn attaches_semicolon_to_last_group_in_semi_statement() { + let src = "fn foo() { + foo(1, 2, 3, 4, 5); +} +"; + let expected = "fn foo() { + foo( + 1, + 2, + 3, + 4, + 5, + ); +} +"; + assert_format_with_max_width(src, expected, " foo(1, 2, 3, 4, 5);".len() - 1); + } + + #[test] + fn attaches_semicolon_to_last_group_in_assign() { + let src = "fn foo() { + a_long_variable = foo(1, 2); +} +"; + let expected = "fn foo() { + a_long_variable = + foo(1, 2); +} +"; + assert_format_with_max_width(src, expected, " a_long_variable = foo(1, 2);".len() - 1); + } + + #[test] + fn long_let_preceded_by_two_newlines() { + let src = "fn foo() { + let y = 0; + + let x = 123456; +} +"; + let expected = src; + assert_format_with_max_width(src, expected, " let x = 123456;".len()); + } +} diff --git a/tooling/nargo_fmt/src/formatter/structs.rs b/tooling/nargo_fmt/src/formatter/structs.rs new file mode 100644 index 00000000000..c26ab552f30 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/structs.rs @@ -0,0 +1,198 @@ +use noirc_frontend::{ + ast::NoirStruct, + token::{Keyword, Token}, +}; + +use super::Formatter; +use crate::chunks::ChunkGroup; + +impl<'a> Formatter<'a> { + pub(super) fn format_struct(&mut self, noir_struct: NoirStruct) { + self.format_secondary_attributes(noir_struct.attributes); + self.write_indentation(); + self.format_item_visibility(noir_struct.visibility); + self.write_keyword(Keyword::Struct); + self.write_space(); + self.write_identifier(noir_struct.name); + self.format_generics(noir_struct.generics); + self.skip_comments_and_whitespace(); + + // A case like `struct Foo;` + if self.is_at(Token::Semicolon) { + self.write_semicolon(); + return; + } + + // A case like `struct Foo { ... }` + self.write_space(); + self.write_left_brace(); + + if noir_struct.fields.is_empty() { + self.format_empty_block_contents(); + } else { + self.increase_indentation(); + self.write_line(); + + for (index, documented_field) in noir_struct.fields.into_iter().enumerate() { + if index > 0 { + self.write_comma(); + self.write_line(); + } + + let doc_comments = documented_field.doc_comments; + if !doc_comments.is_empty() { + self.format_outer_doc_comments(); + } + + let field = documented_field.item; + self.write_indentation(); + self.format_item_visibility(field.visibility); + self.write_identifier(field.name); + self.write_token(Token::Colon); + self.write_space(); + self.format_type(field.typ); + } + + // Take the comment chunk so we can put it after a trailing comma we add, in case there's no comma + let mut group = ChunkGroup::new(); + let mut comments_and_whitespace_chunk = + self.chunk_formatter().skip_comments_and_whitespace_chunk(); + comments_and_whitespace_chunk.string = + comments_and_whitespace_chunk.string.trim_end().to_string(); + group.text(comments_and_whitespace_chunk); + + if self.is_at(Token::Comma) { + self.bump(); + } + self.write(","); + + self.format_chunk_group(group); + self.skip_comments_and_whitespace(); + + self.decrease_indentation(); + self.write_line(); + self.write_indentation(); + } + + self.write_right_brace(); + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + #[test] + fn format_empty_struct_semicolon() { + let src = " mod moo { + /// hello + #[foo] pub ( crate ) struct Foo ; }"; + let expected = "mod moo { + /// hello + #[foo] + pub(crate) struct Foo; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_struct_with_generics() { + let src = " mod moo { struct Foo < A, B, let N : u32 > ; }"; + let expected = "mod moo { + struct Foo; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_struct_with_fields() { + let src = " mod moo { struct Foo { +// hello +/// comment + pub field : Field , + // comment +pub another : ( ), + } }"; + let expected = "mod moo { + struct Foo { + // hello + /// comment + pub field: Field, + // comment + pub another: (), + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_struct_with_multiple_newlines() { + let src = " mod moo { + + + struct Foo { + + +x: Field , + + +y: Field + + +} + + +}"; + let expected = "mod moo { + + struct Foo { + + x: Field, + + y: Field, + } + +} +"; + assert_format(src, expected); + } + + #[test] + fn format_two_structs() { + let src = " struct Foo { } struct Bar {} + "; + let expected = "struct Foo {} +struct Bar {} +"; + assert_format(src, expected); + } + + #[test] + fn format_struct_field_without_trailing_comma_but_comment() { + let src = "struct Foo { + field: Field // comment + }"; + let expected = "struct Foo { + field: Field, // comment +} +"; + assert_format(src, expected); + } + + #[test] + fn format_comment_after_last_struct_field() { + let src = "struct Foo { + field: Field + /* comment */ + }"; + let expected = "struct Foo { + field: Field, + /* comment */ +} +"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/trait_impl.rs b/tooling/nargo_fmt/src/formatter/trait_impl.rs new file mode 100644 index 00000000000..5bb9a0d0025 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/trait_impl.rs @@ -0,0 +1,234 @@ +use noirc_frontend::{ + ast::{NoirTraitImpl, Pattern, TraitImplItem, TraitImplItemKind}, + token::{Keyword, Token}, +}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_trait_impl(&mut self, trait_impl: NoirTraitImpl) { + // skip synthetic trait impl's, e.g. generated from trait aliases + if trait_impl.is_synthetic { + return; + } + + let has_where_clause = !trait_impl.where_clause.is_empty(); + + self.write_indentation(); + self.write_keyword(Keyword::Impl); + self.format_generics(trait_impl.impl_generics); + self.write_space(); + self.format_path(trait_impl.trait_name); + self.format_generic_type_args(trait_impl.trait_generics); + self.write_space(); + self.write_keyword(Keyword::For); + self.write_space(); + self.format_type(trait_impl.object_type); + + if has_where_clause { + self.format_where_clause( + trait_impl.where_clause, + true, // write trailing comma and newline + ); + } else { + self.write_space(); + } + self.write_left_brace(); + + if trait_impl.items.is_empty() { + self.format_empty_block_contents(); + } else { + self.increase_indentation(); + self.write_line(); + + for (index, documented_item) in trait_impl.items.into_iter().enumerate() { + if index > 0 { + self.write_line(); + } + + let doc_comments = documented_item.doc_comments; + let item = documented_item.item; + if !doc_comments.is_empty() { + self.format_outer_doc_comments(); + } + self.format_trait_impl_item(item); + } + + self.skip_comments_and_whitespace(); + self.decrease_indentation(); + self.write_line(); + self.write_indentation(); + } + + self.write_right_brace(); + } + + fn format_trait_impl_item(&mut self, item: TraitImplItem) { + match item.kind { + TraitImplItemKind::Function(noir_function) => { + self.format_function( + noir_function, + true, // skip visibility + ); + } + TraitImplItemKind::Constant(name, typ, value) => { + let pattern = Pattern::Identifier(name); + let chunks = self.chunk_formatter().format_let_or_global( + Keyword::Let, + pattern, + typ, + Some(value), + Vec::new(), // Attributes + ); + + self.write_indentation(); + self.format_chunk_group(chunks); + } + TraitImplItemKind::Type { name, alias } => { + self.write_indentation(); + self.write_keyword(Keyword::Type); + self.write_space(); + self.write_identifier(name); + self.write_space(); + self.write_token(Token::Assign); + self.write_space(); + self.format_type(alias); + self.write_semicolon(); + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + #[test] + fn format_empty_trait_impl() { + let src = " mod moo { impl Foo for Bar { } }"; + let expected = "mod moo { + impl Foo for Bar {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_trait_impl_with_trait_generics() { + let src = " mod moo { impl Foo < T > for Bar { } }"; + let expected = "mod moo { + impl Foo for Bar {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_trait_impl_with_impl_generics() { + let src = " mod moo { impl Default for Option { +} }"; + let expected = "mod moo { + impl Default for Option {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_trait_impl_with_where_clause() { + let src = " mod moo { impl Foo < T > for Bar where T : Baz { } }"; + let expected = "mod moo { + impl Foo for Bar + where + T: Baz, + {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_trait_impl_with_where_clause_with_trait_bound_generics() { + let src = "impl Into for U where T: From { }"; + let expected = "impl Into for U +where + T: From, +{} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_impl_function() { + let src = " mod moo { impl Foo for Bar { + /// Some doc comment +fn foo ( ) { } + } }"; + let expected = "mod moo { + impl Foo for Bar { + /// Some doc comment + fn foo() {} + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_impl_function_with_visibility() { + let src = " mod moo { impl Foo for Bar { + /// Some doc comment +pub fn foo ( ) { } + } }"; + let expected = "mod moo { + impl Foo for Bar { + /// Some doc comment + fn foo() {} + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_impl_constant_without_type() { + let src = " mod moo { impl Foo for Bar { + let X =42 ; + } }"; + let expected = "mod moo { + impl Foo for Bar { + let X = 42; + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_impl_constant_with_type() { + let src = " mod moo { impl Foo for Bar { + let X : i32=42 ; + } }"; + let expected = "mod moo { + impl Foo for Bar { + let X: i32 = 42; + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_impl_type() { + let src = " mod moo { impl Foo for Bar { + type X = i32 ; + } }"; + let expected = "mod moo { + impl Foo for Bar { + type X = i32; + } +} +"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/traits.rs b/tooling/nargo_fmt/src/formatter/traits.rs new file mode 100644 index 00000000000..175dcad6170 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/traits.rs @@ -0,0 +1,331 @@ +use noirc_frontend::{ + ast::{NoirTrait, Param, Pattern, TraitItem, Visibility}, + token::{Attributes, Keyword, Token}, +}; + +use super::{function::FunctionToFormat, Formatter}; + +impl<'a> Formatter<'a> { + pub(super) fn format_trait(&mut self, noir_trait: NoirTrait) { + self.format_secondary_attributes(noir_trait.attributes); + self.write_indentation(); + self.format_item_visibility(noir_trait.visibility); + self.write_keyword(Keyword::Trait); + self.write_space(); + self.write_identifier(noir_trait.name); + self.format_generics(noir_trait.generics); + + if noir_trait.is_alias { + self.write_space(); + self.write_token(Token::Assign); + } + + if !noir_trait.bounds.is_empty() { + self.skip_comments_and_whitespace(); + + if !noir_trait.is_alias { + self.write_token(Token::Colon); + } + + self.write_space(); + + for (index, trait_bound) in noir_trait.bounds.into_iter().enumerate() { + if index > 0 { + self.write_space(); + self.write_token(Token::Plus); + self.write_space(); + } + self.format_trait_bound(trait_bound); + } + } + + if !noir_trait.where_clause.is_empty() { + self.format_where_clause(noir_trait.where_clause, true); + } + + // aliases have ';' in lieu of '{ items }' + if noir_trait.is_alias { + self.write_semicolon(); + return; + } + + self.write_space(); + self.write_left_brace(); + if noir_trait.items.is_empty() { + self.increase_indentation(); + self.skip_comments_and_whitespace(); + self.decrease_indentation(); + } else { + self.increase_indentation(); + self.write_line(); + + for (index, documented_item) in noir_trait.items.into_iter().enumerate() { + if index > 0 { + self.write_line(); + } + + let doc_comments = documented_item.doc_comments; + let item = documented_item.item; + if !doc_comments.is_empty() { + self.format_outer_doc_comments(); + } + self.format_trait_item(item); + } + + self.skip_comments_and_whitespace(); + self.decrease_indentation(); + self.write_line(); + self.write_indentation(); + } + self.write_right_brace(); + } + + fn format_trait_item(&mut self, item: TraitItem) { + match item { + TraitItem::Function { + is_unconstrained: _, + visibility, + is_comptime: _, + name, + generics, + parameters, + return_type, + where_clause, + body, + } => { + let parameters = parameters + .into_iter() + .map(|(name, typ)| Param { + visibility: Visibility::Private, + pattern: Pattern::Identifier(name), + typ, + span: Default::default(), // Doesn't matter + }) + .collect(); + + let func = FunctionToFormat { + attributes: Attributes::empty(), + visibility, + name, + generics, + parameters, + return_type, + return_visibility: Visibility::Private, + where_clause, + body, + skip_visibility: true, + }; + self.format_function_impl(func); + } + TraitItem::Constant { name, typ, default_value } => { + let pattern = Pattern::Identifier(name); + let chunks = self.chunk_formatter().format_let_or_global( + Keyword::Let, + pattern, + typ, + default_value, + Vec::new(), // Attributes + ); + self.write_indentation(); + self.format_chunk_group(chunks); + } + TraitItem::Type { name } => { + self.write_indentation(); + self.write_keyword(Keyword::Type); + self.write_space(); + self.write_identifier(name); + self.write_semicolon(); + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + #[test] + fn format_empty_trait() { + let src = " mod moo { /// Comment + pub trait Foo { } }"; + let expected = "mod moo { + /// Comment + pub trait Foo {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_empty_trait_with_generics() { + let src = " mod moo { trait Foo < A, B, > { } }"; + let expected = "mod moo { + trait Foo {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_parents() { + let src = " mod moo { trait Foo : Bar + Baz { } }"; + let expected = "mod moo { + trait Foo: Bar + Baz {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_where_clause() { + let src = " mod moo { trait Foo < T > where T : Bar { } }"; + let expected = "mod moo { + trait Foo + where + T: Bar, + {} +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_type() { + let src = " mod moo { trait Foo { + /// hello + type X; + } }"; + let expected = "mod moo { + trait Foo { + /// hello + type X; + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_constant_no_value() { + let src = " mod moo { trait Foo { + let x : i32 ; + } }"; + let expected = "mod moo { + trait Foo { + let x: i32; + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_constant_with_value() { + let src = " mod moo { trait Foo { + let x : i32 = 1 ; + } }"; + let expected = "mod moo { + trait Foo { + let x: i32 = 1; + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_function_without_body() { + let src = " mod moo { trait Foo { + /// hello + fn foo ( ); + } }"; + let expected = "mod moo { + trait Foo { + /// hello + fn foo(); + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_function_with_body() { + let src = " mod moo { trait Foo { + /// hello + fn foo ( ) { 1 } + } }"; + let expected = "mod moo { + trait Foo { + /// hello + fn foo() { + 1 + } + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_function_with_params() { + let src = " mod moo { trait Foo { + /// hello + fn foo ( x : i32 , y : Field ); + } }"; + let expected = "mod moo { + trait Foo { + /// hello + fn foo(x: i32, y: Field); + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_function_with_where_clause() { + let src = " mod moo { trait Foo { + fn foo () where T : Bar; + } }"; + let expected = "mod moo { + trait Foo { + fn foo() + where + T: Bar; + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_trait_with_function_with_visibility() { + let src = " mod moo { trait Foo { + /// hello + pub fn foo ( ) { 1 } + } }"; + let expected = "mod moo { + trait Foo { + /// hello + fn foo() { + 1 + } + } +} +"; + assert_format(src, expected); + } + + #[test] + fn format_multiple_traits() { + let src = " trait Foo {} + + trait Bar {}"; + let expected = "trait Foo {} + +trait Bar {} +"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/type_expression.rs b/tooling/nargo_fmt/src/formatter/type_expression.rs new file mode 100644 index 00000000000..95b0c045156 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/type_expression.rs @@ -0,0 +1,38 @@ +use noirc_frontend::{ast::UnresolvedTypeExpression, token::Token}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_type_expression(&mut self, type_expr: UnresolvedTypeExpression) { + self.skip_comments_and_whitespace(); + + // Parenthesized type expressions exist but are not represented in the AST + while let Token::LeftParen = self.token { + self.write_left_paren(); + } + + match type_expr { + UnresolvedTypeExpression::Variable(path) => self.format_path(path), + UnresolvedTypeExpression::Constant(..) => { + self.write_current_token_and_bump(); + } + UnresolvedTypeExpression::BinaryOperation(lhs, _operator, rhs, _span) => { + self.format_type_expression(*lhs); + self.write_space(); + self.write_current_token_and_bump(); + self.write_space(); + self.format_type_expression(*rhs); + } + UnresolvedTypeExpression::AsTraitPath(..) => { + unreachable!("Should not be present in the AST") + } + } + + self.skip_comments_and_whitespace(); + + // Parenthesized type expressions exist but are not represented in the AST + while let Token::RightParen = self.token { + self.write_right_paren(); + } + } +} diff --git a/tooling/nargo_fmt/src/formatter/types.rs b/tooling/nargo_fmt/src/formatter/types.rs new file mode 100644 index 00000000000..e52704ddaa7 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/types.rs @@ -0,0 +1,353 @@ +use noirc_frontend::{ + ast::{AsTraitPath, UnresolvedType, UnresolvedTypeData}, + token::{Keyword, Token}, +}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_type(&mut self, typ: UnresolvedType) { + self.skip_comments_and_whitespace(); + + match typ.typ { + UnresolvedTypeData::Unit => { + self.write_left_paren(); + self.write_right_paren(); + } + UnresolvedTypeData::Bool => { + self.write_keyword(Keyword::Bool); + } + UnresolvedTypeData::Integer(..) | UnresolvedTypeData::FieldElement => { + self.write_current_token_and_bump(); + } + UnresolvedTypeData::Array(type_expr, typ) => { + self.write_left_bracket(); + self.format_type(*typ); + self.write_semicolon(); + self.write_space(); + self.format_type_expression(type_expr); + self.write_right_bracket(); + } + UnresolvedTypeData::Slice(typ) => { + self.write_left_bracket(); + self.format_type(*typ); + self.write_right_bracket(); + } + UnresolvedTypeData::Expression(type_expr) => { + self.format_type_expression(type_expr); + } + UnresolvedTypeData::String(type_expr) => { + self.write_keyword(Keyword::String); + self.write_token(Token::Less); + self.format_type_expression(type_expr); + self.write_token(Token::Greater); + } + UnresolvedTypeData::FormatString(type_expr, typ) => { + self.write_keyword(Keyword::FormatString); + self.write_token(Token::Less); + self.format_type_expression(type_expr); + self.write_comma(); + self.write_space(); + self.format_type(*typ); + self.write_token(Token::Greater); + } + UnresolvedTypeData::Parenthesized(typ) => { + self.write_left_paren(); + self.format_type(*typ); + self.write_right_paren(); + } + UnresolvedTypeData::Named(path, generic_type_args, _) => { + self.format_path(path); + if !generic_type_args.is_empty() { + self.skip_comments_and_whitespace(); + + // Apparently some Named types with generics have `::` before the generics + // while others don't, so we have to account for both cases. + if self.is_at(Token::DoubleColon) { + self.write_token(Token::DoubleColon); + } + self.format_generic_type_args(generic_type_args); + } + } + UnresolvedTypeData::TraitAsType(path, generic_type_args) => { + self.write_keyword(Keyword::Impl); + self.write_space(); + self.format_path(path); + self.format_generic_type_args(generic_type_args); + } + UnresolvedTypeData::MutableReference(typ) => { + self.write_token(Token::Ampersand); + self.write_keyword(Keyword::Mut); + self.write_space(); + self.format_type(*typ); + } + UnresolvedTypeData::Tuple(types) => { + let types_len = types.len(); + + self.write_left_paren(); + for (index, typ) in types.into_iter().enumerate() { + if index > 0 { + self.write_comma(); + self.write_space(); + } + self.format_type(typ); + } + + self.skip_comments_and_whitespace(); + if self.is_at(Token::Comma) { + if types_len == 1 { + self.write_comma(); + } else { + self.bump(); + } + } + + self.write_right_paren(); + } + UnresolvedTypeData::Function(args, return_type, env, unconstrained) => { + if unconstrained { + self.write_keyword(Keyword::Unconstrained); + self.write_space(); + } + + self.write_keyword(Keyword::Fn); + self.skip_comments_and_whitespace(); + + if self.is_at(Token::LeftBracket) { + self.write_left_bracket(); + self.format_type(*env); + self.write_right_bracket(); + } + + self.write_left_paren(); + for (index, arg) in args.into_iter().enumerate() { + if index > 0 { + self.write_comma(); + self.write_space(); + } + self.format_type(arg); + } + + self.skip_comments_and_whitespace(); + // Remove trailing comma if there's one + if self.is_at(Token::Comma) { + self.bump(); + } + + self.write_right_paren(); + self.skip_comments_and_whitespace(); + if self.is_at(Token::Arrow) { + self.write_space(); + self.write_token(Token::Arrow); + self.write_space(); + self.format_type(*return_type); + } + } + UnresolvedTypeData::Quoted(..) => { + self.write_current_token_and_bump(); + } + UnresolvedTypeData::AsTraitPath(as_trait_path) => { + self.format_as_trait_path(*as_trait_path); + } + UnresolvedTypeData::Resolved(..) + | UnresolvedTypeData::Interned(..) + | UnresolvedTypeData::Error => unreachable!("Should not be present in the AST"), + UnresolvedTypeData::Unspecified => panic!("Unspecified type should have been handled"), + } + } + + pub(super) fn format_as_trait_path(&mut self, as_trait_path: AsTraitPath) { + self.write_token(Token::Less); + self.format_type(as_trait_path.typ); + self.write_space(); + self.write_keyword(Keyword::As); + self.write_space(); + self.format_path(as_trait_path.trait_path); + self.format_generic_type_args(as_trait_path.trait_generics); + self.write_token(Token::Greater); + self.write_token(Token::DoubleColon); + self.write_identifier(as_trait_path.impl_item); + } +} + +#[cfg(test)] +mod tests { + use noirc_frontend::parser; + + use crate::Config; + + fn assert_format_type(src: &str, expected: &str) { + let module_src = format!("type X = {};", src); + let (parsed_module, errors) = parser::parse_program(&module_src); + if !errors.is_empty() { + panic!("Expected no errors, got: {:?}", errors); + } + let result = crate::format(&module_src, parsed_module, &Config::default()); + let type_result = &result["type X = ".len()..]; + let type_result = &type_result[..type_result.len() - 2]; + similar_asserts::assert_eq!(type_result, expected); + + let (parsed_module, errors) = parser::parse_program(&result); + if !errors.is_empty() { + panic!("Expected no errors in idempotent check, got: {:?}", errors); + } + let result = crate::format(&result, parsed_module, &Config::default()); + let type_result = &result["type X = ".len()..]; + let type_result = &type_result[..type_result.len() - 2]; + similar_asserts::assert_eq!(type_result, expected); + } + + #[test] + fn format_unit_type() { + let src = " ( ) "; + let expected = "()"; + assert_format_type(src, expected); + } + + #[test] + fn format_bool_type() { + let src = " bool "; + let expected = "bool"; + assert_format_type(src, expected); + } + + #[test] + fn format_integer_type() { + let src = " i32 "; + let expected = "i32"; + assert_format_type(src, expected); + } + + #[test] + fn format_named_type() { + let src = " foo :: bar :: Baz "; + let expected = "foo::bar::Baz"; + assert_format_type(src, expected); + } + + #[test] + fn format_named_type_with_generics() { + let src = " foo :: bar < A, B = Field , C = i32 , D , >"; + let expected = "foo::bar"; + assert_format_type(src, expected); + } + + #[test] + fn format_array_type_with_constant() { + let src = " [ Field ; 1 ] "; + let expected = "[Field; 1]"; + assert_format_type(src, expected); + } + + #[test] + fn format_array_type_with_var() { + let src = " [ Field ; LEN ] "; + let expected = "[Field; LEN]"; + assert_format_type(src, expected); + } + + #[test] + fn format_array_type_with_binary() { + let src = " [ Field ; 1+2 ] "; + let expected = "[Field; 1 + 2]"; + assert_format_type(src, expected); + } + + #[test] + fn format_array_type_with_parenthesized() { + let src = " [ Field ; ( 1 + 2 ) * ( 3 + 4 ) ] "; + let expected = "[Field; (1 + 2) * (3 + 4)]"; + assert_format_type(src, expected); + } + + #[test] + fn format_slice_type() { + let src = " [ Field ] "; + let expected = "[Field]"; + assert_format_type(src, expected); + } + + #[test] + fn format_mutable_reference_type() { + let src = " & mut Field "; + let expected = "&mut Field"; + assert_format_type(src, expected); + } + + #[test] + fn format_parenthesized_type() { + let src = " ( Field )"; + let expected = "(Field)"; + assert_format_type(src, expected); + } + + #[test] + fn format_simple_function_type() { + let src = " fn ( ) -> Field "; + let expected = "fn() -> Field"; + assert_format_type(src, expected); + } + + #[test] + fn format_function_type_with_args_and_unconstrained() { + let src = " unconstrained fn ( Field , i32 , ) -> Field "; + let expected = "unconstrained fn(Field, i32) -> Field"; + assert_format_type(src, expected); + } + + #[test] + fn format_function_type_with_env() { + let src = " fn [ Env ] ( ) -> Field "; + let expected = "fn[Env]() -> Field"; + assert_format_type(src, expected); + } + + #[test] + fn format_tuple_type_one_type() { + let src = " ( Field , )"; + let expected = "(Field,)"; + assert_format_type(src, expected); + } + + #[test] + fn format_tuple_type_two_types() { + let src = " ( Field , i32 , )"; + let expected = "(Field, i32)"; + assert_format_type(src, expected); + } + + #[test] + fn format_trait_as_type() { + let src = " impl Foo < Bar > "; + let expected = "impl Foo"; + assert_format_type(src, expected); + } + + #[test] + fn format_string_type() { + let src = "str < 6 >"; + let expected = "str<6>"; + assert_format_type(src, expected); + } + + #[test] + fn format_fmtstr_type() { + let src = "fmtstr < 6, ( ) >"; + let expected = "fmtstr<6, ()>"; + assert_format_type(src, expected); + } + + #[test] + fn format_quoted_type() { + let src = " Expr "; + let expected = "Expr"; + assert_format_type(src, expected); + } + + #[test] + fn format_as_trait_path_type() { + let src = " < Field as foo :: Bar> :: baz "; + let expected = "::baz"; + assert_format_type(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/use_tree.rs b/tooling/nargo_fmt/src/formatter/use_tree.rs new file mode 100644 index 00000000000..98d63ef6611 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/use_tree.rs @@ -0,0 +1,263 @@ +use noirc_frontend::{ + ast::{ItemVisibility, UseTree, UseTreeKind}, + token::{Keyword, Token}, +}; + +use crate::chunks::{Chunk, ChunkFormatter, ChunkGroup}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_import(&mut self, use_tree: UseTree, visibility: ItemVisibility) { + let group = self.chunk_formatter().format_import(use_tree, visibility); + + self.write_indentation(); + self.format_chunk_group(group); + } +} + +impl<'a, 'b> ChunkFormatter<'a, 'b> { + pub(super) fn format_import( + &mut self, + use_tree: UseTree, + visibility: ItemVisibility, + ) -> ChunkGroup { + let mut group = ChunkGroup::new(); + + group.text(self.chunk(|formatter| { + formatter.format_item_visibility(visibility); + formatter.write_keyword(Keyword::Use); + formatter.write_space(); + })); + + group.group(self.format_use_tree(use_tree)); + group.semicolon(self); + + group + } + + fn format_use_tree(&mut self, use_tree: UseTree) -> ChunkGroup { + let mut group = ChunkGroup::new(); + group.one_chunk_per_line = false; + + if !use_tree.prefix.is_empty() { + group.text(self.chunk(|formatter| { + let has_segments = !use_tree.prefix.segments.is_empty(); + + formatter.format_path(use_tree.prefix); + + // If the path has segments, like in `foo` or `crate::foo`, we need to add a double colon. + // But for example for `crate::` we don't need to add a double colon (there are no segments + // and `crate::` was already written). + if has_segments { + formatter.write_token(Token::DoubleColon); + } + })); + } + + match use_tree.kind { + UseTreeKind::Path(name, alias) => { + group.text(self.chunk(|formatter| { + formatter.write_identifier(name); + if let Some(alias) = alias { + formatter.write_space(); + formatter.write_keyword(Keyword::As); + formatter.write_space(); + formatter.write_identifier(alias); + } + })); + } + UseTreeKind::List(use_trees) => { + // We check if there are nested lists. If yes, then each item will be on a separate line + // (it reads better, and this is what rustfmt seems to do too) + let has_nested_list = + use_trees.iter().any(|use_tree| matches!(use_tree.kind, UseTreeKind::List(..))); + + let use_trees_len = use_trees.len(); + + let left_brace_chunk = self.chunk(|formatter| { + formatter.write_left_brace(); + }); + + let comments_count_before = self.written_comments_count; + + let mut items_chunk = ChunkGroup::new(); + self.format_items_separated_by_comma( + use_trees, + false, // force trailing comma + false, // surround with spaces + &mut items_chunk, + |formatter, use_tree, chunks| chunks.group(formatter.format_use_tree(use_tree)), + ); + + let wrote_comment = self.written_comments_count > comments_count_before; + + let right_brace_chunk = self.chunk(|formatter| { + formatter.write_right_brace(); + }); + + if use_trees_len == 1 && !wrote_comment { + // We are only interested in keeping the single Group: everything else + // is lines, indentation and trailing comma that we don't need and would + // actually produce incorrect code. + let single_group = + items_chunk.chunks.into_iter().filter_map(Chunk::group).next().unwrap(); + group.chunks.extend(single_group.chunks); + } else { + if has_nested_list { + group.one_chunk_per_line = true; + } + + group.text(left_brace_chunk); + group.chunks.extend(items_chunk.chunks); + group.text(right_brace_chunk); + } + } + } + + group + } +} + +#[cfg(test)] +mod tests { + use crate::{assert_format_with_config, config::ImportsGranularity, Config}; + + fn assert_format(src: &str, expected: &str) { + let config = Config { + imports_granularity: ImportsGranularity::Preserve, + reorder_imports: false, + ..Config::default() + }; + assert_format_with_config(src, expected, config); + } + + fn assert_format_with_max_width(src: &str, expected: &str, max_width: usize) { + let config = Config { + imports_granularity: ImportsGranularity::Preserve, + reorder_imports: false, + max_width, + ..Config::default() + }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn format_simple_use_without_alias() { + let src = " mod moo { pub use foo ; }"; + let expected = "mod moo { + pub use foo; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_simple_use_with_alias() { + let src = " mod moo { use foo :: bar as baz ; }"; + let expected = "mod moo { + use foo::bar as baz; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_simple_use_with_path_kind() { + let src = "use super :: foo ;"; + let expected = "use super::foo;\n"; + assert_format(src, expected); + } + + #[test] + fn format_use_list_two_items() { + let src = " use foo::{ bar, baz };"; + let expected = "use foo::{bar, baz};\n"; + assert_format(src, expected); + } + + #[test] + fn format_use_trees_with_max_width() { + let src = " use foo::{ bar, baz , qux , one::{two, three} };"; + let expected = "use foo::{ + bar, + baz, + qux, + one::{ + two, three, + }, +}; +"; + assert_format_with_max_width(src, expected, 20); + } + + #[test] + fn format_use_list_one_item() { + let src = " use foo::{ bar, };"; + let expected = "use foo::bar;\n"; + assert_format(src, expected); + } + + #[test] + fn format_long_use_list_one_item() { + let src = "use one::two::{three::{four, five}};"; + let expected = "use one::two::three::{ + four, five, +}; +"; + assert_format_with_max_width(src, expected, 25); + } + + #[test] + fn format_use_list_one_item_with_comments() { + let src = " use foo::{ /* do not remove me */ bar, };"; + let expected = "use foo::{/* do not remove me */ bar};\n"; + assert_format(src, expected); + } + + #[test] + fn format_use_crate_with_list() { + let src = " use crate :: hash :: { Hash, Hasher }; "; + let expected = "use crate::hash::{Hash, Hasher};\n"; + assert_format(src, expected); + } + + #[test] + fn attaches_semicolon_to_last_group() { + let src = " use crate::hash::{Hash, Hasher}; "; + let expected = "use crate::hash::{ + Hash, Hasher, +}; +"; + assert_format_with_max_width(src, expected, "use crate::hash::{Hash, Hasher}".len()); + } + + #[test] + fn do_not_merge_and_sort_imports() { + let src = " +use aztec::{ + context::Context, log::emit_unencrypted_log, note::{ + note_getter_options::NoteGetterOptions, note_header::NoteHeader, + }, state_vars::{ + Map, PrivateSet, PublicMutable, + }, types::{ + address::AztecAddress, type_serialization::field_serialization::{ + FIELD_SERIALIZED_LEN, FieldSerializationMethods, + }, + }, +}; + "; + let expected = "use aztec::{ + context::Context, + log::emit_unencrypted_log, + note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, + state_vars::{Map, PrivateSet, PublicMutable}, + types::{ + address::AztecAddress, + type_serialization::field_serialization::{FIELD_SERIALIZED_LEN, FieldSerializationMethods}, + }, +}; +"; + assert_format(src, expected); + } +} diff --git a/tooling/nargo_fmt/src/formatter/use_tree_merge.rs b/tooling/nargo_fmt/src/formatter/use_tree_merge.rs new file mode 100644 index 00000000000..a679e026435 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/use_tree_merge.rs @@ -0,0 +1,634 @@ +use std::{cmp::Ordering, collections::BTreeMap, fmt::Display}; + +use noirc_frontend::ast::{ItemVisibility, PathKind, UseTree, UseTreeKind}; + +use crate::{ + chunks::{ChunkGroup, TextChunk}, + config::ImportsGranularity, +}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn merge_and_format_imports( + &mut self, + imports: Vec, + visibility: ItemVisibility, + ) { + match self.config.imports_granularity { + ImportsGranularity::Preserve => { + let mut import_trees: Vec = + imports.into_iter().map(|import| merge_imports(vec![import])).collect(); + import_trees.sort(); + + for (index, import_tree) in import_trees.into_iter().enumerate() { + if index > 0 { + self.write_line_without_skipping_whitespace_and_comments(); + } + + self.format_import_tree(import_tree, visibility); + } + } + ImportsGranularity::Crate => { + let import_tree = merge_imports(imports); + self.format_import_tree(import_tree, visibility); + } + } + } + + fn format_import_tree(&mut self, import_tree: ImportTree, visibility: ItemVisibility) { + for (index, (segment, segment_tree)) in import_tree.tree.into_iter().enumerate() { + if index > 0 { + self.write_line_without_skipping_whitespace_and_comments(); + } + + let tree = ImportTree::single(segment, *segment_tree); + let tree = tree.simplify(); + + let group = format_merged_import_with_visibility(tree, visibility); + self.write_indentation(); + self.format_chunk_group(group); + } + } +} + +// The logic here is similar to that of `use_tree.rs`, except that it works with ImportTree +// instead of UseTree and we never check or advance the lexer. + +fn format_merged_import_with_visibility( + mut import_tree: ImportTree, + visibility: ItemVisibility, +) -> ChunkGroup { + let mut group = ChunkGroup::new(); + match visibility { + ItemVisibility::Private => (), + ItemVisibility::PublicCrate => { + group.text(TextChunk::new("pub(crate) ".to_string())); + } + ItemVisibility::Public => { + group.text(TextChunk::new("pub ".to_string())); + } + } + group.text(TextChunk::new("use ".to_string())); + + let (segment, tree) = import_tree.tree.pop_first().unwrap(); + assert!(import_tree.tree.is_empty()); + + group.group(format_merged_import(segment, *tree)); + group.text_attached_to_last_group(TextChunk::new(";".to_string())); + group +} + +fn format_merged_import(segment: Segment, import_tree: ImportTree) -> ChunkGroup { + let mut group = ChunkGroup::new(); + + group.text(TextChunk::new(segment.to_string())); + + if import_tree.tree.is_empty() { + return group; + } + + // We check if there are nested lists. If yes, then each item will be on a separate line + // (it reads better, and this is what rustfmt seems to do too) + if import_tree.tree.values().all(|tree| tree.tree.is_empty()) { + group.one_chunk_per_line = false; + } + + group.text(TextChunk::new("::{".to_string())); + group.increase_indentation(); + group.line(); + + for (index, (segment, import_tree)) in import_tree.tree.into_iter().enumerate() { + if index > 0 { + group.text_attached_to_last_group(TextChunk::new(",".to_string())); + group.space_or_line(); + } + + group.group(format_merged_import(segment, *import_tree)); + } + + group.trailing_comma(); + group.decrease_indentation(); + group.line(); + group.text(TextChunk::new("}".to_string())); + + group +} + +/// We keep Crate, Super and Dep as special segments so that they are ordered in that way +/// (they'll come in that order before any plain segment). +#[derive(Debug, PartialEq, Eq)] +enum Segment { + /// Represents the end of a path. + /// This is needed because we have want to merge "foo" and "foo::bar", + /// we need to know that "foo" is the end of a path, and "foo::bar" is another one. + /// If we don't, merging "foo" and "foo::bar" will result in just "foo::bar", loosing "foo", + /// when we actually want "foo::{self, bar}". + SelfReference, + Crate, + Super, + Dep, + Plain(String), +} + +impl Segment { + /// Combines two segments into a single one, by joining them with "::". + fn combine(self, other: Segment) -> Segment { + if other == Segment::SelfReference { + self + } else { + Segment::Plain(format!("{}::{}", self, other)) + } + } + + fn order_number(&self) -> usize { + match self { + Segment::SelfReference => 0, + Segment::Crate => 1, + Segment::Super => 2, + Segment::Dep => 3, + Segment::Plain(_) => 4, + } + } +} + +impl Display for Segment { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Segment::Crate => write!(f, "crate"), + Segment::Super => write!(f, "super"), + Segment::Dep => write!(f, "dep"), + Segment::Plain(s) => write!(f, "{}", s), + Segment::SelfReference => write!(f, "self"), + } + } +} + +impl PartialOrd for Segment { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Segment { + fn cmp(&self, other: &Self) -> Ordering { + let order_number_ordering = self.order_number().cmp(&other.order_number()); + if order_number_ordering != Ordering::Equal { + return order_number_ordering; + } + + if let (Segment::Plain(self_string), Segment::Plain(other_string)) = (self, other) { + // Case-insensitive comparison for plain segments + let ordering = self_string.to_lowercase().cmp(&other_string.to_lowercase()); + if ordering == Ordering::Equal { + self_string.cmp(other_string) + } else { + ordering + } + } else { + order_number_ordering + } + } +} + +/// An import tree to represent merged imports. +/// For example for the given imports: +/// +/// use foo::bar::{baz, qux}; +/// use foo::another; +/// +/// an ImportTree that represents the merged imports would be: +/// +/// { +/// "foo" => { +/// "another" => {} +/// "bar" => {"baz", "qux"}, +/// } +/// } +#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord)] +struct ImportTree { + tree: BTreeMap>, +} + +impl ImportTree { + fn new() -> Self { + Self { tree: BTreeMap::new() } + } + + /// Creates an import tree that has `segment` as the only element with `tree` as its value. + fn single(segment: Segment, tree: ImportTree) -> Self { + let mut tree_map = BTreeMap::new(); + tree_map.insert(segment, Box::new(tree)); + Self { tree: tree_map } + } + + /// Inserts a segment to the tree, creating the necessary empty children if they don't exist yet. + fn insert(&mut self, segment: Segment) -> &mut ImportTree { + self.tree.entry(segment).or_default() + } + + /// Simplifies a tree by combining segments that only have one child. + /// + /// For example, this tree: + /// + /// { + /// "foo" => { + /// "bar" => {"baz", "qux"} + /// } + /// } + /// + /// will be simplified to: + /// + /// { + /// "foo::bar" => {"baz", "qux"} + /// } + fn simplify(self) -> ImportTree { + let mut new_tree = ImportTree::new(); + for (segment, tree) in self.tree.into_iter() { + let mut tree = tree.simplify(); + if tree.tree.len() == 1 { + let (first_segment, first_tree) = tree.tree.pop_first().unwrap(); + let new_segment = segment.combine(first_segment); + new_tree.tree.insert(new_segment, first_tree); + } else { + new_tree.tree.insert(segment, Box::new(tree)); + } + } + new_tree + } +} + +/// Combines all use trees to form a single ImportTree. +fn merge_imports(imports: Vec) -> ImportTree { + let mut tree = ImportTree::new(); + merge_imports_in_tree(imports, &mut tree); + tree +} + +fn merge_imports_in_tree(imports: Vec, mut tree: &mut ImportTree) { + for import in imports { + let mut tree = match import.prefix.kind { + PathKind::Crate => tree.insert(Segment::Crate), + PathKind::Super => tree.insert(Segment::Super), + PathKind::Dep => tree.insert(Segment::Dep), + PathKind::Plain => &mut tree, + }; + + for segment in import.prefix.segments { + tree = tree.insert(Segment::Plain(segment.ident.to_string())); + } + + match import.kind { + UseTreeKind::Path(ident, alias) => { + if let Some(alias) = alias { + tree = tree.insert(Segment::Plain(format!("{} as {}", ident, alias))); + tree.insert(Segment::SelfReference); + } else if ident.0.contents == "self" { + tree.insert(Segment::SelfReference); + } else { + tree = tree.insert(Segment::Plain(ident.to_string())); + tree.insert(Segment::SelfReference); + } + } + UseTreeKind::List(trees) => { + merge_imports_in_tree(trees, tree); + } + } + } +} + +#[cfg(test)] +mod tests { + use crate::{assert_format_with_config, config::ImportsGranularity, Config}; + + fn assert_format(src: &str, expected: &str) { + let config = Config { + imports_granularity: ImportsGranularity::Crate, + reorder_imports: true, + ..Config::default() + }; + assert_format_with_config(src, expected, config); + } + + fn assert_format_with_max_width(src: &str, expected: &str, max_width: usize) { + let config = Config { + imports_granularity: ImportsGranularity::Crate, + reorder_imports: true, + max_width, + ..Config::default() + }; + assert_format_with_config(src, expected, config); + } + + fn assert_format_preserving_granularity(src: &str, expected: &str) { + let config = Config { + imports_granularity: ImportsGranularity::Preserve, + reorder_imports: true, + ..Config::default() + }; + assert_format_with_config(src, expected, config); + } + + #[test] + fn format_simple_use_without_alias() { + let src = " mod moo { pub use foo ; }"; + let expected = "mod moo { + pub use foo; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_simple_use_with_alias() { + let src = " mod moo { use foo :: bar as baz ; }"; + let expected = "mod moo { + use foo::bar as baz; +} +"; + assert_format(src, expected); + } + + #[test] + fn format_simple_use_with_path_kind() { + let src = "use super :: foo ;"; + let expected = "use super::foo;\n"; + assert_format(src, expected); + } + + #[test] + fn format_use_list_two_items() { + let src = " use foo::{ bar, baz };"; + let expected = "use foo::{bar, baz};\n"; + assert_format(src, expected); + } + + #[test] + fn format_use_trees_with_max_width() { + let src = " use foo::{ bar, baz , qux , one::{two, three} };"; + let expected = "use foo::{ + bar, + baz, + one::{ + three, two, + }, + qux, +}; +"; + assert_format_with_max_width(src, expected, 20); + } + + #[test] + fn format_use_list_one_item() { + let src = " use foo::{ bar, };"; + let expected = "use foo::bar;\n"; + assert_format(src, expected); + } + + #[test] + fn format_long_use_list_one_item() { + let src = "use one::two::{three::{four, five}};"; + let expected = "use one::two::three::{ + five, four, +}; +"; + assert_format_with_max_width(src, expected, 25); + } + + #[test] + fn format_use_list_one_item_with_comments() { + let src = " use foo::{ /* do not remove me */ bar, };"; + let expected = "use foo::{/* do not remove me */ bar};\n"; + assert_format(src, expected); + } + + #[test] + fn format_use_crate_with_list() { + let src = " use crate :: hash :: { Hash, Hasher }; "; + let expected = "use crate::hash::{Hash, Hasher};\n"; + assert_format(src, expected); + } + + #[test] + fn attaches_semicolon_to_last_group() { + let src = " use crate::hash::{Hash, Hasher}; "; + let expected = "use crate::hash::{ + Hash, Hasher, +}; +"; + assert_format_with_max_width(src, expected, "use crate::hash::{Hash, Hasher}".len()); + } + + #[test] + fn does_not_merge_imports_if_they_are_separated_by_two_lines() { + let src = " + use foo::baz; + + use foo::{def, abc}; +"; + let expected = "use foo::baz; + +use foo::{abc, def}; +"; + assert_format(src, expected); + } + + #[test] + fn does_not_merge_imports_if_they_have_different_visibilities() { + let src = " + pub use foo::baz; + use foo::{def, abc}; +"; + let expected = "pub use foo::baz; +use foo::{abc, def}; +"; + assert_format(src, expected); + } + + #[test] + fn does_not_merge_imports_if_they_have_trailing_comments_on_the_first_use() { + let src = " + use foo; // trailing + use bar; + + fn foo() {} +"; + let expected = "use foo; // trailing +use bar; + +fn foo() {} +"; + assert_format(src, expected); + } + + #[test] + fn does_not_merge_imports_if_they_have_trailing_comments_followed_by_item() { + let src = " + use foo; + use bar; // trailing + + fn foo() {} +"; + let expected = "use foo; +use bar; // trailing + +fn foo() {} +"; + assert_format(src, expected); + } + + #[test] + fn does_not_merge_imports_if_they_have_trailing_comments_followed_by_nothing() { + let src = " + use foo; + use bar; // trailing +"; + let expected = "use foo; +use bar; // trailing +"; + assert_format(src, expected); + } + + #[test] + fn merges_and_sorts_imports_just_two() { + let src = " + use foo::baz; + use foo::bar; + "; + let expected = "use foo::{bar, baz};\n"; + assert_format(src, expected); + } + + #[test] + fn sorts_but_not_merges_if_not_told_so() { + let src = " + use foo::baz; + use foo::{qux, bar}; + use bar; + "; + let expected = "use bar; +use foo::{bar, qux}; +use foo::baz; +"; + assert_format_preserving_granularity(src, expected); + } + + #[test] + fn does_not_sort_imports_in_separate_groups() { + let src = " + use foo::baz; + use foo::{qux, bar}; + + use bar; + "; + let expected = "use foo::{bar, qux}; +use foo::baz; + +use bar; +"; + assert_format_preserving_granularity(src, expected); + } + + #[test] + fn merges_and_sorts_imports_2() { + let src = " +use aztec::{ + context::Context, log::emit_unencrypted_log, note::{ + note_getter_options::NoteGetterOptions, note_header::NoteHeader, + }, state_vars::{ + Map, PrivateSet, PublicMutable, + }, types::{ + address::AztecAddress, type_serialization::field_serialization::{ + FIELD_SERIALIZED_LEN, FieldSerializationMethods, + }, + }, +}; + "; + let expected = "use aztec::{ + context::Context, + log::emit_unencrypted_log, + note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, + state_vars::{Map, PrivateSet, PublicMutable}, + types::{ + address::AztecAddress, + type_serialization::field_serialization::{FIELD_SERIALIZED_LEN, FieldSerializationMethods}, + }, +}; +"; + assert_format(src, expected); + } + + #[test] + fn merges_and_sorts_imports_with_different_path_kinds() { + let src = " + use bar::baz; + use foo::bar; + use crate::foo; + "; + let expected = "use crate::foo; +use bar::baz; +use foo::bar; +"; + assert_format(src, expected); + } + + #[test] + fn sorts_import() { + let src = " + use value_note::{ + utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, + }; + "; + let expected = "use value_note::{ + utils::{decrement, increment}, + value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, +}; +"; + assert_format(src, expected); + } + + #[test] + fn sorts_import_ignoring_case() { + let src = " + use foo::{def, ZETA, ABC, efg}; + use BAR; + "; + let expected = "use BAR; +use foo::{ABC, def, efg, ZETA}; +"; + assert_format(src, expected); + } + + #[test] + fn merges_nested_import() { + let src = " + use foo::bar; + use foo; + "; + let expected = "use foo::{self, bar};\n"; + assert_format(src, expected); + } + + #[test] + fn idempotent_test_check_next_test() { + let src = " + use std::as_witness; +use std::merkle::compute_merkle_root; + "; + let expected = "use std::{as_witness, merkle::compute_merkle_root};\n"; + assert_format(src, expected); + } + + #[test] + fn idempotent_test_check_previous_test() { + let src = "use std::{as_witness, merkle::compute_merkle_root};"; + let expected = "use std::{as_witness, merkle::compute_merkle_root};\n"; + assert_format(src, expected); + } + + #[test] + fn does_not_merge_same_identifiers_if_equal_case_insensitive() { + let src = "use bigint::{BigNum, bignum::BigNumTrait};\n"; + assert_format(src, src); + } +} diff --git a/tooling/nargo_fmt/src/formatter/visibility.rs b/tooling/nargo_fmt/src/formatter/visibility.rs new file mode 100644 index 00000000000..27441b977bb --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/visibility.rs @@ -0,0 +1,51 @@ +use super::Formatter; +use noirc_frontend::{ + ast::{ItemVisibility, Visibility}, + token::Keyword, +}; + +impl<'a> Formatter<'a> { + pub(super) fn format_item_visibility(&mut self, visibility: ItemVisibility) { + self.skip_comments_and_whitespace(); + + match visibility { + ItemVisibility::Private => (), + ItemVisibility::PublicCrate => { + self.write_keyword(Keyword::Pub); + self.write_left_paren(); + self.write_keyword(Keyword::Crate); + self.write_right_paren(); + self.write_space(); + } + ItemVisibility::Public => { + self.write_keyword(Keyword::Pub); + self.write_space(); + } + } + } + + pub(super) fn format_visibility(&mut self, visibility: Visibility) { + self.skip_comments_and_whitespace(); + + match visibility { + Visibility::Private => (), + Visibility::Public => { + self.write_keyword(Keyword::Pub); + self.write_space(); + } + Visibility::CallData(..) => { + self.write_keyword(Keyword::CallData); + self.write_left_paren(); + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); + self.skip_comments_and_whitespace(); + self.write_right_paren(); + self.write_space(); + } + Visibility::ReturnData => { + self.write_keyword(Keyword::ReturnData); + self.write_space(); + } + } + } +} diff --git a/tooling/nargo_fmt/src/formatter/where_clause.rs b/tooling/nargo_fmt/src/formatter/where_clause.rs new file mode 100644 index 00000000000..538d2ba8c01 --- /dev/null +++ b/tooling/nargo_fmt/src/formatter/where_clause.rs @@ -0,0 +1,72 @@ +use noirc_frontend::{ + ast::{TraitBound, UnresolvedTraitConstraint}, + token::{Keyword, Token}, +}; + +use super::Formatter; + +impl<'a> Formatter<'a> { + pub(super) fn format_where_clause( + &mut self, + constraints: Vec, + write_trailing_comma_and_new_line: bool, + ) { + assert!(!constraints.is_empty()); + + self.skip_comments_and_whitespace(); + self.write_line(); + self.write_indentation(); + self.write_keyword(Keyword::Where); + self.increase_indentation(); + + // If we have `where F: Foo + Bar`, that's actually parsed as two constraints: `F: Foo` and `F: Bar`. + // To format it we'll have to skip the second type `F` if we find a `+` token. + let mut write_type = true; + + for constraint in constraints { + if write_type { + self.write_line(); + self.write_indentation(); + self.format_type(constraint.typ); + self.write_token(Token::Colon); + self.write_space(); + } + + self.format_trait_bound(constraint.trait_bound); + self.skip_comments_and_whitespace(); + + if self.is_at(Token::Plus) { + self.write_space(); + self.write_token(Token::Plus); + self.write_space(); + write_type = false; + continue; + } + + write_type = true; + + if self.is_at(Token::Comma) { + if write_trailing_comma_and_new_line { + self.write_token(Token::Comma); + } else { + self.skip_comments_and_whitespace(); + self.bump(); + } + } else if write_trailing_comma_and_new_line { + self.write(","); + } + } + + self.decrease_indentation(); + + if write_trailing_comma_and_new_line { + self.write_line(); + self.write_indentation(); + } + } + + pub(super) fn format_trait_bound(&mut self, trait_bound: TraitBound) { + self.format_path(trait_bound.trait_path); + self.format_generic_type_args(trait_bound.trait_generics); + } +} diff --git a/tooling/nargo_fmt/src/lib.rs b/tooling/nargo_fmt/src/lib.rs new file mode 100644 index 00000000000..05bfb0e7d57 --- /dev/null +++ b/tooling/nargo_fmt/src/lib.rs @@ -0,0 +1,91 @@ +#![forbid(unsafe_code)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + +//! The Noir formatter. +//! +//! It works by using two techniques: +//! +//! 1. Surfing a parsed module by using a lexer. +//! 2. Trying to not exceed the maximum line width by formatting to intermediate chunk (see chunks.rs) +//! +//! What is lexer surfing? +//! +//! Suppose we need to format this code: +//! +//! fn foo ( ) { let x : Field = ( 2 , 3 ) ; } +//! +//! We first parse the above code so we end up with a ParsedModule. Next we traverse this module +//! contents and process each item, statement, expression, type, etc., we find. +//! +//! For example, the first thing we'll find is a function. We know it has no visibility and no doc +//! comments so we can expect an `fn` keyword to be there. We write it. Next will come the identifier. +//! For that we "skip" any spaces and comments between `fn` and `foo`, writing only one space instead +//! of possibly multiple spaces, then write "foo". If there were comments between `fn` and `foo`, +//! we write them (the formatter will never lose comments). +//! +//! Next we know there are no generics, so we can expect a `(`, etc. +//! +//! In this way we go token by token, inserting newlines when needed, removing extra spaces, +//! indenting things as we go deep inside structures, etc. +//! +//! But that's not all. The formatter will try to not exceed the configurable maximum width. +//! It will do that but, for simplicity, only for function parameters list, statements and expressions +//! (we assume an `impl Foo ...` line won't exceed the maximum length, and if it does it's not a big deal, +//! or we can always improve things later). For this, read the comments in chunks.rs. +mod chunks; +mod config; +pub mod errors; +mod formatter; + +use formatter::Formatter; +use noirc_frontend::ParsedModule; + +pub use config::Config; + +pub fn format(source: &str, parsed_module: ParsedModule, config: &Config) -> String { + let mut formatter = Formatter::new(source, config); + formatter.format_program(parsed_module); + formatter.buffer.contents() +} + +#[cfg(test)] +pub(crate) fn assert_format(src: &str, expected: &str) { + assert_format_with_config(src, expected, Config::default()); +} + +#[cfg(test)] +pub(crate) fn assert_format_with_max_width(src: &str, expected: &str, max_width: usize) { + let config = Config { max_width, ..Config::default() }; + assert_format_with_config(src, expected, config); +} + +#[cfg(test)] +pub(crate) fn assert_format_with_config(src: &str, expected: &str, config: Config) { + use noirc_frontend::parser; + + let (parsed_module, errors) = parser::parse_program(src); + let errors: Vec<_> = errors.into_iter().filter(|error| !error.is_warning()).collect(); + if !errors.is_empty() { + panic!("Expected no errors, got: {:?}", errors); + } + let result = format(src, parsed_module, &config); + if result != expected { + println!("Expected:\n~~~\n{}\n~~~\nGot:\n~~~\n{}\n~~~", expected, result); + } + + similar_asserts::assert_eq!(result, expected); + + let src = &result; + let (parsed_module, errors) = parser::parse_program(src); + let errors: Vec<_> = errors.into_iter().filter(|error| !error.is_warning()).collect(); + if !errors.is_empty() { + panic!("Expected no errors in idempotent check, got: {:?}", errors); + } + let result = format(src, parsed_module, &config); + if result != expected { + println!("Expected (idempotent):\n~~~\n{}\n~~~\nGot:\n~~~\n{}\n~~~", expected, result); + } + similar_asserts::assert_eq!(result, expected, "idempotent check failed"); +} diff --git a/tooling/nargo_fmt/tests/execute.rs b/tooling/nargo_fmt/tests/execute.rs new file mode 100644 index 00000000000..d8802fd926b --- /dev/null +++ b/tooling/nargo_fmt/tests/execute.rs @@ -0,0 +1,5 @@ +#[cfg(test)] +mod tests { + // include tests generated by `build.rs` + include!(concat!(env!("OUT_DIR"), "/execute.rs")); +} diff --git a/tooling/nargo_fmt/tests/expected/add.nr b/tooling/nargo_fmt/tests/expected/add.nr new file mode 100644 index 00000000000..341ed06f3e6 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/add.nr @@ -0,0 +1,7 @@ +fn main(mut x: u32, y: u32, z: u32) { + x += y; + assert(x == z); + + x *= 8; + assert(x > 9); +} diff --git a/tooling/nargo_fmt/tests/expected/array.nr b/tooling/nargo_fmt/tests/expected/array.nr new file mode 100644 index 00000000000..b8e7d051368 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/array.nr @@ -0,0 +1,53 @@ +fn big_array() { + [ + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, + 10000000000000000, + 100000000000000000, + 1000000000000000000, + 10000000000000000000, + 100000000000000000000, + 1000000000000000000000, + 10000000000000000000000, + 100000000000000000000000, + 1000000000000000000000000, + ]; + + [1, 10]; + + [ + // hello! + 1, 10, + ]; + + [ + // hello! + 1, + // asd + 10, + ]; + + [ + // hello! + 1, + // asd + 10, + // asdasd + ]; + + [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]]; +} diff --git a/tooling/nargo_fmt/tests/expected/assert.nr b/tooling/nargo_fmt/tests/expected/assert.nr new file mode 100644 index 00000000000..805e069c9a7 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/assert.nr @@ -0,0 +1,5 @@ +fn main(x: Field) { + assert(x == 0, "with a message"); + assert_eq(x, 1); + assert(x, message); +} diff --git a/tooling/nargo_fmt/tests/expected/call.nr b/tooling/nargo_fmt/tests/expected/call.nr new file mode 100644 index 00000000000..8a1a529dfb7 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/call.nr @@ -0,0 +1,46 @@ +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 + ); + + outer_function( + some_function(), // Original inner function call + another_function(), // Original inner function call + ); + + my_function( + // Comment + some_value, + /* Multiline + Comment */ + another_func(20, 30), + ); + + my_function( + some_function(10, "arg1", another_function()), + another_func(20, some_function(), 30), + ); + + outer_function( + some_function(), + another_function(some_function(), some_value), + ); + + assert_eq(x, y); + + assert_eq(x, y, "message"); + + assert(x); + + assert(x, "message"); + + assert(x == y); + + assert(p4_affine.eq(Gaffine::new( + 6890855772600357754907169075114257697580319025794532037257385534741338397365, + 4338620300185947561074059802482547481416142213883829469920100239455078257889, + ))); +} diff --git a/tooling/nargo_fmt/tests/expected/cast.nr b/tooling/nargo_fmt/tests/expected/cast.nr new file mode 100644 index 00000000000..63008168f84 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/cast.nr @@ -0,0 +1,3 @@ +fn main() { + x as u8 +} diff --git a/tooling/nargo_fmt/tests/expected/comment.nr b/tooling/nargo_fmt/tests/expected/comment.nr new file mode 100644 index 00000000000..fae425acfd0 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/comment.nr @@ -0,0 +1,27 @@ +fn comment1() { + // +} + +// random comment + +fn comment2() { // Test +} + +fn comment3() // some comment +{} + +fn comment4() +// some comment +{} + +fn comment5() // some comment +{} + +fn comment6() // some comment some comment some comment some comment some comment some comment so +{} + +fn comment7() +// some comment some comment some comment some comment some comment some comment some comment +{} + +fn comment8(/*test*/) {} diff --git a/tooling/nargo_fmt/tests/expected/contract.nr b/tooling/nargo_fmt/tests/expected/contract.nr new file mode 100644 index 00000000000..86f8d56b62d --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/contract.nr @@ -0,0 +1,90 @@ +// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +// Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. +// Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +contract Benchmarking { + use aztec::protocol_types::abis::function_selector::FunctionSelector; + + use value_note::{ + utils::{decrement, increment}, + value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, + }; + + use aztec::{ + context::Context, + log::emit_unencrypted_log, + note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, + state_vars::{Map, PrivateSet, PublicMutable}, + types::{ + address::AztecAddress, + type_serialization::field_serialization::{ + FIELD_SERIALIZED_LEN, FieldSerializationMethods, + }, + }, + }; + + struct Storage { + notes: Map>, + balances: Map>, + } + + impl Storage { + fn init(context: Context) -> pub Self { + Storage { + notes: Map::new( + context, + 1, + |context, slot| PrivateSet::new(context, slot, ValueNoteMethods), + ), + balances: Map::new( + context, + 2, + |context, slot| { + PublicMutable::new(context, slot, FieldSerializationMethods) + }, + ), + } + } + } + + #[aztec(private)] + fn constructor() {} + + // Nec tincidunt praesent semper feugiat nibh sed pulvinar. Nibh nisl condimentum id venenatis a. + #[aztec(private)] + fn create_note(owner: Field, value: Field) { + increment(storage.notes.at(owner), value, owner); + } + + // Diam quam nulla porttitor massa id. Elit ullamcorper dignissim cras tincidunt lobortis feugiat. + #[aztec(private)] + fn recreate_note(owner: Field, index: u32) { + let owner_notes = storage.notes.at(owner); + let getter_options = NoteGetterOptions::new().set_limit(1).set_offset(index); + let notes = owner_notes.get_notes(getter_options); + let note = notes[0].unwrap_unchecked(); + owner_notes.remove(note); + increment(owner_notes, note.value, owner); + } + + // Ultrices in iaculis nunc sed augue lacus. + #[aztec(public)] + fn increment_balance(owner: Field, value: Field) { + let current = storage.balances.at(owner).read(); + storage.balances.at(owner).write(current + value); + let _callStackItem1 = context.call_public_function( + context.this_address(), + comptime { FunctionSelector::from_signature("broadcast(Field)") }, + [owner], + ); + } + + // Est ultricies integer quis auctor elit sed. In nibh mauris cursus mattis molestie a iaculis. + #[aztec(public)] + fn broadcast(owner: Field) { + emit_unencrypted_log(&mut context, storage.balances.at(owner).read()); + } +} + +// Uses the token bridge contract, which tells which input token we need to talk to and handles the exit funds to L1 +contract Uniswap {} diff --git a/tooling/nargo_fmt/tests/expected/databus.nr b/tooling/nargo_fmt/tests/expected/databus.nr new file mode 100644 index 00000000000..0e9761ed52d --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/databus.nr @@ -0,0 +1,2 @@ +fn main(x: pub u8, y: call_data(0) u8) -> return_data u32 {} + diff --git a/tooling/nargo_fmt/tests/expected/empty.nr b/tooling/nargo_fmt/tests/expected/empty.nr new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/empty.nr @@ -0,0 +1 @@ + diff --git a/tooling/nargo_fmt/tests/expected/expr.nr b/tooling/nargo_fmt/tests/expected/expr.nr new file mode 100644 index 00000000000..9bee940f900 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/expr.nr @@ -0,0 +1,139 @@ +// Test some empty blocks. +fn qux() { + {} + + { /* a block with a comment */ } + {} + { + // A block with a comment. + } + + { + { + { + // A block with a comment. + } + } + } +} + +fn foo_return() { + "yay" +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock() { + { + { + { + "inner-block" + } + } + } +} + +fn comment() { + // this is a test comment + 1 +} + +fn only_comment() { + // Keep this here +} + +fn only_comments() { + // Keep this here + // Keep this here +} + +fn only_comments() { + // Keep this here + // Keep this here +} + +fn commnet() { + 1 + // +} + +fn test() { + 34 +} + +fn test() { + // 324 + 34 +} + +fn line() { + 42; // 42 +} + +fn line() { + 42; // 42 + 42; + // hello +} + +fn line() { + 42; // 42 + // 42 + // hello +} + +fn parenthesized() { + value + (x as Field) +} + +fn parenthesized() { + (i as u8) + (j as u8) + (k as u8) + x + y + z +} + +fn parenthesized() { + value + ( /*test*/ x as Field /*test*/) +} + +fn parenthesized() { + value + + ( + // line + x as Field + ) +} + +fn constructor() { + Point { x: 5, y: 10 }; +} + +fn if_expr() { + if true { + println("Hello :D"); + } +} + +fn return_if_expr() { + if true { + 42 + } else { + 40 + 2 + } +} + +fn return_if_expr() { + if true { 42 }; + + if true { + 42 + } else { + 40 + 2 + } +} + +fn if_if() { + (if cond { some(); } else { none(); }).bar().baz(); +} diff --git a/tooling/nargo_fmt/tests/expected/fn.nr b/tooling/nargo_fmt/tests/expected/fn.nr new file mode 100644 index 00000000000..afdb8883e15 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/fn.nr @@ -0,0 +1,98 @@ +fn main(x: pub u8, y: u8) {} + +fn main(x: pub u8, y: u8) -> pub Field {} + +fn main(x: A, y: B) -> pub Field +where + A: Eq, + B: Eq, +{} + +fn main() +// hello +{} + +fn main( + // hello +) {} + +fn main( + // hello + unit: (), +) {} + +fn main() +where + T: Eq, +{} + +fn main( + tape: [Field; TAPE_LEN], + initial_registers: [Field; REGISTER_COUNT], + initial_memory: [Field; MEM_COUNT], + initial_program_counter: Field, + initial_call_stack: [Field; MAX_CALL_STACK], + initial_call_stack_pointer: u64, +) -> pub ExecutionResult {} + +fn apply_binary_field_op( + lhs: RegisterIndex, + rhs: RegisterIndex, + result: RegisterIndex, + op: u8, + registers: &mut Registers, +) -> bool {} + +fn main() -> pub [Field; 2] {} + +fn ret_normal_lambda1() -> ((fn() -> Field)) {} + +fn ret_normal_lambda1() -> fn() -> Field {} + +fn ret_closure1() -> fn[(Field,)]() -> Field {} + +fn ret_closure2() -> fn[(Field, Field)]() -> Field {} + +fn ret_closure3() -> fn[(u32, u64)]() -> u64 {} + +fn make_counter() -> fn[(&mut Field,)]() -> Field {} + +fn get_some(generator: fn[Env]() -> Field) -> [Field; 5] {} + +fn main( + message: [u8; 10], + message_field: Field, + pub_key_x: Field, + pub_key_y: Field, + signature: [u8; 64], +) {} + +pub fn from_baz(x: [Field; crate::foo::MAGIC_NUMBER]) {} + +fn id(x: [Field; I]) -> [Field; I] {} + +fn id_two(x: [Field; I]) -> [Field; I] {} + +fn whitespace_before_generics(foo: T) {} + +fn more_whitespace_before_generics(foo: T) {} + +fn with_unconstrained(x: unconstrained fn() -> ()) {} + +pub(crate) fn one() {} + +pub unconstrained fn two() {} + +pub unconstrained comptime fn two() {} + +/// Documented +#[test] +fn three() {} + +#[test(should_fail)] +// comment +fn four() {} + +#[test(should_fail_with = "oops")] +fn five() {} + diff --git a/tooling/nargo_fmt/tests/expected/for.nr b/tooling/nargo_fmt/tests/expected/for.nr new file mode 100644 index 00000000000..748c1fe008d --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/for.nr @@ -0,0 +1,25 @@ +fn for_stmt() { + for elem in self { + ret &= predicate(elem); + } +} + +fn for_stmt() { + for i in 0..(C1 - 1) { + for _j in 1..(C1 - i - 1) { + b *= b; + } + + for k in 0..=C1 { + d *= d; + } + + z *= if b == 1 { 1 } else { c }; + + c *= c; + + t *= if b == 1 { 1 } else { c }; + + b = t; + } +} diff --git a/tooling/nargo_fmt/tests/expected/global.nr b/tooling/nargo_fmt/tests/expected/global.nr new file mode 100644 index 00000000000..e73cf96ccbe --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/global.nr @@ -0,0 +1,9 @@ +//! Super module :] + +// super global variable +global answer = 42; + +// Super module :] + +// super global variable +global answer = 42; diff --git a/tooling/nargo_fmt/tests/expected/if.nr b/tooling/nargo_fmt/tests/expected/if.nr new file mode 100644 index 00000000000..fa0d10a819b --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/if.nr @@ -0,0 +1,56 @@ +//@error_on_lost_comment=false +fn main() { + let (x, y) = if is_square(gx1) { + (x1, sqrt(gx1)) + } else { + (x2, sqrt(gx2)) + }; + + let n = if x != y { + if x != 20 { + slice.push_back(y) + } else { + slice + } + } else { + slice + }; + + if false { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + let a = if 0 > 1 { 0 } else { 0 }; + + if true { + (); + } else if false { + (); + (); + } else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tooling/nargo_fmt/tests/expected/ignore.nr b/tooling/nargo_fmt/tests/expected/ignore.nr new file mode 100644 index 00000000000..6e957539405 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/ignore.nr @@ -0,0 +1,27 @@ +fn main() { + // noir-fmt:ignore + assert( x != y ); + assert(x != y); + { + // noir-fmt:ignore + }; + assert(x != y); +} +// noir-fmt:ignore +fn main() { +1; +2; +3; +} +// noir-fmt:ignore +mod items { +fn hello() {} +} + +fn mk_array() { + // noir-fmt:ignore + let array = [1, + ]; + let array = [1]; +} + diff --git a/tooling/nargo_fmt/tests/expected/impl.nr b/tooling/nargo_fmt/tests/expected/impl.nr new file mode 100644 index 00000000000..d3f986ca943 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/impl.nr @@ -0,0 +1,34 @@ +impl MyType {} + +impl MyType {} + +impl MyType {} + +impl MyType { + fn method(self) {} + + fn method(mut self) {} + + fn method(&mut self) {} + + fn method(self: Self) {} + + fn method(mut self: Self) {} +} + +impl MyType { + fn method(self) {} +} + +impl MyType { + fn method(self) {} +} + +impl MyStruct +where + T: MyEq, +{ + fn my_eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.my_eq(other.b) + } +} 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..f931a06c96c --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/impl_trait_fn_parameter.nr @@ -0,0 +1,6 @@ +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..9c74c477f5f --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/import_braces.nr @@ -0,0 +1 @@ +use std::hash::sha256; diff --git a/tooling/nargo_fmt/tests/expected/index.nr b/tooling/nargo_fmt/tests/expected/index.nr new file mode 100644 index 00000000000..74356a9013f --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/index.nr @@ -0,0 +1,11 @@ +fn foo() { + let arr = [10, 20, 30, 40]; + arr[2]; + arr[2]; + arr[/*test*/ 2]; + arr[2/*test*/]; + arr[ + // test + 2 + ]; +} diff --git a/tooling/nargo_fmt/tests/expected/infix.nr b/tooling/nargo_fmt/tests/expected/infix.nr new file mode 100644 index 00000000000..7a43f4a70a1 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/infix.nr @@ -0,0 +1,20 @@ +//@error_on_lost_comment=false +fn foo() { + 40 + 2; + !40 + 2; + 40 + 2 == 42; + + 40 /*test*/ + 2 == 42; + 40 + 2 /*test*/ == 42; +} + +fn big() { + assert( + bjj_affine.contains(bjj_affine.gen) + & bjj_affine.contains(p1_affine) + & bjj_affine.contains(p2_affine) + & bjj_affine.contains(p3_affine) + & bjj_affine.contains(p4_affine) + & bjj_affine.contains(p5_affine), + ); +} diff --git a/tooling/nargo_fmt/tests/expected/let.nr b/tooling/nargo_fmt/tests/expected/let.nr new file mode 100644 index 00000000000..b5806d5f3d3 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/let.nr @@ -0,0 +1,69 @@ +//@error_on_lost_comment=false +fn let_() { + let fn_call = my_function( + some_function(10, "arg1", another_function()), + another_func(20, some_function(), 30), + ); + let array = [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]]; + + let padded_sha256_hash: [u8; 259] = [ + // Padded hash + 209, 50, 135, 178, 4, 155, 190, 229, 228, 111, 61, 174, 8, 49, 48, 116, 90, 226, 77, 7, 111, + 27, 19, 113, 154, 48, 138, 136, 138, 15, 230, 132, 32, 4, 0, 5, 1, 2, 4, 3, 101, 1, 72, 134, + 96, 9, 6, 13, 48, 49, 48, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, + // Rest is padded with 0s until max bytes + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + + let a = BigUint56 { + limbs: [ + 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ], + }; + + let person = Person { + first_name: "John", + last_name: "Doe", + home_address: Address { street: "123 Main St", city: "Exampleville", zip_code: "12345" }, + }; + + let person = Person { + first_name: "John", + last_name: "Doe", + home_address: Address { + street: "123 Main St", + city: "Exampleville", + zip_code: "12345", + master: Person { + first_name: "John", + last_name: "Doe", + home_address: Address { + street: "123 Main St", + city: "Exampleville", + zip_code: "12345", + }, + }, + }, + }; + + let expr = MyExpr { + // A boolean literal (true, false). + kind: ExprKind::Bool(true), + }; + + let expr = MyExpr { /*A boolean literal (true, false).*/ kind: ExprKind::Bool(true) }; + + let mut V = crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct {}; + let mut V = crate2::MyStruct { /*test*/ }; + let mut V = crate2::MyStruct { + // sad + }; +} diff --git a/tooling/nargo_fmt/tests/expected/literals.nr b/tooling/nargo_fmt/tests/expected/literals.nr new file mode 100644 index 00000000000..5a9a735337f --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/literals.nr @@ -0,0 +1,24 @@ +//@error_on_lost_comment=false +fn main() { + [1, 2, 3, 4, 5]; + + [1; 5]; + + [0xff; 5]; + + [0 as u8; MAX_BYTES]; + + true; + + "hello world"; + + "hell\0\"world"; + + f"i: {i}, j: {j}"; + + (); + + (/*test*/); + + () +} diff --git a/tooling/nargo_fmt/tests/expected/member_access.nr b/tooling/nargo_fmt/tests/expected/member_access.nr new file mode 100644 index 00000000000..2330ec826c7 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/member_access.nr @@ -0,0 +1,15 @@ +struct Address { + city: String, + country: String, +} + +struct Person { + name: String, + age: u8, + address: Address, +} + +fn foo(p: Person) { + p.name; + p.address.country; +} diff --git a/tooling/nargo_fmt/tests/expected/method_call.nr b/tooling/nargo_fmt/tests/expected/method_call.nr new file mode 100644 index 00000000000..c2ee71237f8 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/method_call.nr @@ -0,0 +1,3 @@ +fn foo() { + my_object.some_method(10, var_value, inner_method(20, 30)); +} diff --git a/tooling/nargo_fmt/tests/expected/module.nr b/tooling/nargo_fmt/tests/expected/module.nr new file mode 100644 index 00000000000..9f8fb53d5cd --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/module.nr @@ -0,0 +1,39 @@ +#![inner] +#![inner2] + +mod a { + mod b { + struct Data { + a: Field, + } + } + + fn data(a: Field) -> Data { + Data { a } + } + + fn data2(a: Field) -> Data2 { + Data2 { a } + } + + #[custom] + #[another_custom] + mod tests { + #[test] + fn test() { + data(1); + data2(1); + } + } + + #[attr] + mod baz; + + mod empty { + #![inner] + } +} + +pub(crate) mod one {} + +pub mod two {} diff --git a/tooling/nargo_fmt/tests/expected/nested_if_else.nr b/tooling/nargo_fmt/tests/expected/nested_if_else.nr new file mode 100644 index 00000000000..dfd203189e8 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/nested_if_else.nr @@ -0,0 +1,9 @@ +fn nested_if_else() { + if false { + 1 + } else if false { + 2 + } else { + 3 + } +} diff --git a/tooling/nargo_fmt/tests/expected/nested_parens.nr b/tooling/nargo_fmt/tests/expected/nested_parens.nr new file mode 100644 index 00000000000..53eaa63c279 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/nested_parens.nr @@ -0,0 +1,5 @@ +//@remove_nested_parens=false +fn main() { + ((())); + ((((((((())))))))); +} diff --git a/tooling/nargo_fmt/tests/expected/parens.nr b/tooling/nargo_fmt/tests/expected/parens.nr new file mode 100644 index 00000000000..2eaf3838ed6 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/parens.nr @@ -0,0 +1,51 @@ +fn main(x: u64, y: pub u64) { + ( + // + 1 + ); + + ( + // a + 1 + // b + ); + + ( + // test + 1 + ); + + ( + // 1 + ( + // 2 + 2 + ) + ); + + ( + /*a*/ + + ( + // test + 1 + ) + /*b*/ + ); + + ( + // test + 1 + ); + + ( /*a*/ 1); + + (1 /*b*/); + + ( /*c*/ 1 /*d*/); + + ( /*test*/ 1 /*test 2*/); + + (()); + (()); +} diff --git a/tooling/nargo_fmt/tests/expected/print.nr b/tooling/nargo_fmt/tests/expected/print.nr new file mode 100644 index 00000000000..d8404f674b0 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/print.nr @@ -0,0 +1,4 @@ +fn main() { + std::print("Hello world"); + std::println("Hello world"); +} diff --git a/tooling/nargo_fmt/tests/expected/print2.nr b/tooling/nargo_fmt/tests/expected/print2.nr new file mode 100644 index 00000000000..d8404f674b0 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/print2.nr @@ -0,0 +1,4 @@ +fn main() { + std::print("Hello world"); + std::println("Hello world"); +} diff --git a/tooling/nargo_fmt/tests/expected/read_array.nr b/tooling/nargo_fmt/tests/expected/read_array.nr new file mode 100644 index 00000000000..d2619884b5d --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/read_array.nr @@ -0,0 +1,6 @@ +fn read_array(x: [Field; 3]) { + assert(x[0] == 1); + let y = [1, 5, 27]; + + assert(y[x[0]] == 5); +} diff --git a/tooling/nargo_fmt/tests/expected/single_fn.nr b/tooling/nargo_fmt/tests/expected/single_fn.nr new file mode 100644 index 00000000000..b02291fc50d --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/single_fn.nr @@ -0,0 +1,3 @@ +fn main() { + // hello +} diff --git a/tooling/nargo_fmt/tests/expected/single_mod.nr b/tooling/nargo_fmt/tests/expected/single_mod.nr new file mode 100644 index 00000000000..3c04a12d34b --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/single_mod.nr @@ -0,0 +1 @@ +mod hello {} diff --git a/tooling/nargo_fmt/tests/expected/singleton_import.nr b/tooling/nargo_fmt/tests/expected/singleton_import.nr new file mode 100644 index 00000000000..bb1bad500d9 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/singleton_import.nr @@ -0,0 +1,2 @@ +use dep::std; +use some_crate; diff --git a/tooling/nargo_fmt/tests/expected/struct.nr b/tooling/nargo_fmt/tests/expected/struct.nr new file mode 100644 index 00000000000..d7a0cfc6d7c --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/struct.nr @@ -0,0 +1,73 @@ +struct Foo { + bar: Field, + array: [Field; 2], +} + +struct Pair { + first: Foo, + pub second: Field, +} + +impl Foo { + fn default(x: Field, y: Field) -> Self { + Self { bar: 0, array: [x, y] } + } +} + +impl Pair { + fn foo(p: Self) -> Foo { + p.first + } + + fn bar(self) -> Field { + self.foo().bar + } +} + +struct Nested { + a: Field, + b: Field, +} +struct MyStruct { + my_bool: bool, + my_int: u32, + my_nest: Nested, +} +fn test_struct_in_tuple(a_bool: bool, x: Field, y: Field) -> (MyStruct, bool) { + let my_struct = MyStruct { my_bool: a_bool, my_int: 5, my_nest: Nested { a: x, b: y } }; + (my_struct, a_bool) +} + +struct Animal { + legs: Field, + eyes: u8, +} + +fn get_dog() -> Animal { + let dog = Animal { legs: 4, eyes: 2 }; + dog +} + +fn main(x: Field, y: Field) { + let first = Foo::default(x, y); + let p = Pair { first, second: 1 }; + + assert(p.bar() == x); + assert(p.second == y); + assert(p.first.array[0] != p.first.array[1]); + + // Nested structs + let (struct_from_tuple, a_bool) = test_struct_in_tuple(true, x, y); + assert(struct_from_tuple.my_bool == true); + assert(a_bool == true); + assert(struct_from_tuple.my_int == 5); + assert(struct_from_tuple.my_nest.a == 0); + + // Regression test for issue #670 + let Animal { legs, eyes } = get_dog(); + let six = legs + eyes as Field; + + assert(six == 6); + + let Animal { legs: _, eyes: _ } = get_dog(); +} diff --git a/tooling/nargo_fmt/tests/expected/submodule.nr b/tooling/nargo_fmt/tests/expected/submodule.nr new file mode 100644 index 00000000000..88e005b7ac2 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/submodule.nr @@ -0,0 +1,30 @@ +mod a { + // hello +} + +mod a { + // hello + mod b { + // hello + } +} + +mod a { + mod b { + mod c {} + } +} + +mod a { + // 1 + // 2 + // 3 + /*test*/ +} + +mod a { + /**/ + mod b { + mod c {} + } +} diff --git a/tooling/nargo_fmt/tests/expected/trait.nr b/tooling/nargo_fmt/tests/expected/trait.nr new file mode 100644 index 00000000000..0467585fac3 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/trait.nr @@ -0,0 +1,2 @@ +trait Foo: Bar + Baz {} + diff --git a/tooling/nargo_fmt/tests/expected/trait_alias.nr b/tooling/nargo_fmt/tests/expected/trait_alias.nr new file mode 100644 index 00000000000..926f3160279 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/trait_alias.nr @@ -0,0 +1,86 @@ +trait Foo { + fn foo(self) -> Self; +} + +trait Baz = Foo; + +impl Foo for Field { + fn foo(self) -> Self { + self + } +} + +fn baz(x: T) -> T +where + T: Baz, +{ + x.foo() +} + +pub trait Foo_2 { + fn foo_2(self) -> Self; +} + +pub trait Bar_2 { + fn bar_2(self) -> Self; +} + +pub trait Baz_2 = Foo_2 + Bar_2; + +fn baz_2(x: T) -> T +where + T: Baz_2, +{ + x.foo_2().bar_2() +} + +impl Foo_2 for Field { + fn foo_2(self) -> Self { + self + 1 + } +} + +impl Bar_2 for Field { + fn bar_2(self) -> Self { + self + 2 + } +} + +trait Foo_3 { + fn foo_3(self) -> Self; +} + +trait Bar_3 { + fn bar_3(self) -> T; +} + +trait Baz_3 = Foo_3 + Bar_3; + +fn baz_3(x: T) -> U +where + T: Baz_3, +{ + x.foo_3().bar_3() +} + +impl Foo_3 for Field { + fn foo_3(self) -> Self { + self + 1 + } +} + +impl Bar_3 for Field { + fn bar_3(self) -> bool { + true + } +} + +fn main() { + let x: Field = 0; + let _ = baz(x); + + assert(0.foo_2().bar_2() == baz_2(0)); + + assert(0.foo_3().bar_3() == baz_3(0)); +} + diff --git a/tooling/nargo_fmt/tests/expected/tuple.nr b/tooling/nargo_fmt/tests/expected/tuple.nr new file mode 100644 index 00000000000..29f32f83e55 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/tuple.nr @@ -0,0 +1,46 @@ +fn main() { + (1,); + ( + // hello + 1, + ); + (/*hello*/ 1,); + (1/*hello*/,); + (1,); + (/*test*/ 1,); + (/*a*/ 1/*b*/,); + (/*a*/ 1/*b*/, /*c*/ 2/*d*/, /*c*/ 2/*d*/); + (/*a*/ 1/*b*/, /*c*/ 2/*d*/, /*c*/ 2/*d*/, /*e*/ 3/*f*/); + + (1 /*1*/, 2 /* 2*/); + + (1 /*test*/,); + + ( + // + 1, + ); + + ( + // 1 + 1, + // 2, + 2, + ); + + (/*1*/ 1, /*2*/ 2); + + ( + ( + ( + //2 + 1, + ), + ), + ); + ( + /*a*/ 1 + /*b*/, /*c*/ + 2/*d*/, /*c*/ 2/*d*/, /*e*/ 3,/*f*/ + ); +} 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..aac36db7985 --- /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..cd09d7fea56 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/turbofish_method_call.nr @@ -0,0 +1,8 @@ +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/expected/unary_operators.nr b/tooling/nargo_fmt/tests/expected/unary_operators.nr new file mode 100644 index 00000000000..ffea1713c06 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/unary_operators.nr @@ -0,0 +1,10 @@ +//@error_on_lost_comment=false +fn main() { + -1; + -/*test*/1; + -/*test*/1; + + &mut 1; + *v; + ***v; +} diff --git a/tooling/nargo_fmt/tests/expected/unsafe.nr b/tooling/nargo_fmt/tests/expected/unsafe.nr new file mode 100644 index 00000000000..0cf587ea549 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/unsafe.nr @@ -0,0 +1,10 @@ +fn main(x: pub u8, y: u8) { + /// Safety: testing + unsafe {} + + /// Safety: testing + unsafe { + assert_eq(x, y); + } +} + diff --git a/tooling/nargo_fmt/tests/expected/use_super.nr b/tooling/nargo_fmt/tests/expected/use_super.nr new file mode 100644 index 00000000000..91fbe7a9df1 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/use_super.nr @@ -0,0 +1,5 @@ +fn some_func() {} + +mod foo { + use super::some_func; +} diff --git a/tooling/nargo_fmt/tests/expected/vec.nr b/tooling/nargo_fmt/tests/expected/vec.nr new file mode 100644 index 00000000000..15c198efafb --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/vec.nr @@ -0,0 +1,60 @@ +struct Vec { + slice: [T], +} + +// A mutable vector type implemented as a wrapper around immutable slices. +// A separate type is technically not needed but helps differentiate which operations are mutable. +impl Vec { + pub fn new() -> Self { + Self { slice: [] } + } + + // Create a Vec containing each element from the given slice. + // Mutations to the resulting Vec will not affect the original slice. + pub fn from_slice(slice: [T]) -> Self { + Self { slice } + } + + /// 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: Field) -> T { + self.slice[index] + } + + /// Push a new element to the end of the vector, returning a + /// new vector with a length one greater than the + /// original unmodified vector. + pub fn push(&mut self, elem: T) { + self.slice = self.slice.push_back(elem); + } + + /// Pop an element from the end of the given vector, returning + /// a new vector with a length of one less than the given vector, + /// as well as the popped element. + /// Panics if the given vector's length is zero. + pub fn pop(&mut self) -> T { + let (popped_slice, last_elem) = self.slice.pop_back(); + self.slice = popped_slice; + last_elem + } + + /// Insert an element at a specified index, shifting all elements + /// after it to the right + pub fn insert(&mut self, index: Field, 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: Field) -> 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) -> Field { + self.slice.len() + } +} diff --git a/tooling/nargo_fmt/tests/input/add.nr b/tooling/nargo_fmt/tests/input/add.nr new file mode 100644 index 00000000000..6f2892942c1 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/add.nr @@ -0,0 +1,7 @@ +fn main(mut x: u32, y: u32, z: u32) { + x += y; + assert(x == z); + + x *= 8; + assert(x>9); +} diff --git a/tooling/nargo_fmt/tests/input/array.nr b/tooling/nargo_fmt/tests/input/array.nr new file mode 100644 index 00000000000..73651ef76bd --- /dev/null +++ b/tooling/nargo_fmt/tests/input/array.nr @@ -0,0 +1,39 @@ +fn big_array() { + [ + 1,10,100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000, + 10000000000000000000, + 100000000000000000000, + 1000000000000000000000, + 10000000000000000000000, + 100000000000000000000000, + 1000000000000000000000000, + ]; + + [ + 1, + 10, + ]; + + [ +// hello! +1, +10, + ]; + + [ +// hello! +1, +// asd +10, + ]; + + [ +// hello! +1, +// asd +10, +// asdasd + ]; + + [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]]; +} diff --git a/tooling/nargo_fmt/tests/input/assert.nr b/tooling/nargo_fmt/tests/input/assert.nr new file mode 100644 index 00000000000..d0259da0e24 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/assert.nr @@ -0,0 +1,8 @@ +fn main(x: Field) { + assert(x == 0, "with a message"); + assert_eq( + x, + 1 + ); + assert( x, message ); +} diff --git a/tooling/nargo_fmt/tests/input/call.nr b/tooling/nargo_fmt/tests/input/call.nr new file mode 100644 index 00000000000..2e9a612e6d8 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/call.nr @@ -0,0 +1,47 @@ +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 + ); + + outer_function( + + + some_function(), // Original inner function call + another_function(), // Original inner function call + ); + + my_function( + // Comment + some_value, + /* Multiline + Comment */ + another_func( 20, 30 ) + ); + + my_function( + some_function( 10, "arg1", another_function() ), + another_func (20, some_function() , 30 ) + ); + + outer_function( + some_function(), + + + another_function( + some_function(), some_value) + ); + + assert_eq( x, y ); + + assert_eq( x, y, "message" ); + + assert( x ); + + assert( x, "message" ); + + assert( x == y ); + + assert(p4_affine.eq(Gaffine::new(6890855772600357754907169075114257697580319025794532037257385534741338397365, 4338620300185947561074059802482547481416142213883829469920100239455078257889))); +} diff --git a/tooling/nargo_fmt/tests/input/cast.nr b/tooling/nargo_fmt/tests/input/cast.nr new file mode 100644 index 00000000000..dfbb370e2bb --- /dev/null +++ b/tooling/nargo_fmt/tests/input/cast.nr @@ -0,0 +1,4 @@ +fn main() { + +x as u8 +} diff --git a/tooling/nargo_fmt/tests/input/comment.nr b/tooling/nargo_fmt/tests/input/comment.nr new file mode 100644 index 00000000000..0e203a82d66 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/comment.nr @@ -0,0 +1,32 @@ +fn comment1() { + // +} + +// random comment + +fn comment2() { // Test +} + +fn comment3() // some comment +{ +} + +fn comment4() +// some comment +{ +} + +fn comment5() // some comment +{ +} + +fn comment6() // some comment some comment some comment some comment some comment some comment so +{ +} + +fn comment7() +// some comment some comment some comment some comment some comment some comment some comment +{ +} + +fn comment8(/*test*/) {} diff --git a/tooling/nargo_fmt/tests/input/contract.nr b/tooling/nargo_fmt/tests/input/contract.nr new file mode 100644 index 00000000000..cb7505f845c --- /dev/null +++ b/tooling/nargo_fmt/tests/input/contract.nr @@ -0,0 +1,81 @@ +// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +// Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. +// Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +contract Benchmarking { + use aztec::protocol_types::abis::function_selector::FunctionSelector; + + use value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; + + use aztec::{ + 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 + }; + + struct Storage { + notes: Map>, + balances: Map>, + } + + impl Storage { + fn init(context: Context) -> pub Self { + Storage { + notes: Map::new( + context, + 1, + |context, slot| { PrivateSet::new(context, slot, ValueNoteMethods) } + ), + balances: Map::new( + context, + 2, + |context, slot| { PublicMutable::new(context, slot, FieldSerializationMethods) } + ) + } + } + } + + #[aztec(private)] + fn constructor() {} + + // Nec tincidunt praesent semper feugiat nibh sed pulvinar. Nibh nisl condimentum id venenatis a. + #[aztec(private)] + fn create_note(owner: Field, value: Field) { + increment(storage.notes.at(owner), value, owner); + } + + // Diam quam nulla porttitor massa id. Elit ullamcorper dignissim cras tincidunt lobortis feugiat. + #[aztec(private)] + fn recreate_note(owner: Field, index: u32) { + let owner_notes = storage.notes.at(owner); + let getter_options = NoteGetterOptions::new().set_limit(1).set_offset(index); + let notes = owner_notes.get_notes(getter_options); + let note = notes[0].unwrap_unchecked(); + owner_notes.remove(note); + increment(owner_notes, note.value, owner); + } + + // Ultrices in iaculis nunc sed augue lacus. + #[aztec(public)] + fn increment_balance(owner: Field, value: Field) { + let current = storage.balances.at(owner).read(); + storage.balances.at(owner).write(current + value); + let _callStackItem1 = context.call_public_function( + context.this_address(), + comptime { + FunctionSelector::from_signature("broadcast(Field)") + }, + [owner] + ); + } + + // Est ultricies integer quis auctor elit sed. In nibh mauris cursus mattis molestie a iaculis. + #[aztec(public)] + fn broadcast(owner: Field) { + emit_unencrypted_log(&mut context, storage.balances.at(owner).read()); + } +} + +// Uses the token bridge contract, which tells which input token we need to talk to and handles the exit funds to L1 +contract Uniswap {} diff --git a/tooling/nargo_fmt/tests/input/databus.nr b/tooling/nargo_fmt/tests/input/databus.nr new file mode 100644 index 00000000000..e47fcc50210 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/databus.nr @@ -0,0 +1,2 @@ +fn main(x: pub u8, y: call_data(0) u8) -> return_data u32 { } + diff --git a/tooling/nargo_fmt/tests/input/empty.nr b/tooling/nargo_fmt/tests/input/empty.nr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tooling/nargo_fmt/tests/input/expr.nr b/tooling/nargo_fmt/tests/input/expr.nr new file mode 100644 index 00000000000..9ecefad7dfd --- /dev/null +++ b/tooling/nargo_fmt/tests/input/expr.nr @@ -0,0 +1,153 @@ +// Test some empty blocks. +fn qux() { + {} + + { /* a block with a comment */ } + { + + } + { + // A block with a comment. + } + + { + { + { + // A block with a comment. + } + } + } +} + +fn foo_return() { + "yay" +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock() { + { + { + { + "inner-block" + } + } + } +} + +fn comment() { + // this is a test comment + 1 +} + +fn only_comment() { + // Keep this here +} + +fn only_comments() { +// Keep this here +// Keep this here +} + +fn only_comments() { + // Keep this here + // Keep this here +} + +fn commnet() { + 1 + // +} + +fn test() { + + + + + + 34 +} + +fn test() { + + + + + // 324 + 34 +} + +fn line() { + 42; // 42 +} + + +fn line() { + 42;// 42 + 42; +// hello +} + + +fn line() { + 42;// 42 + // 42 +// hello +} + +fn parenthesized() { + value + ( x as Field ) +} + +fn parenthesized() { + ( i as u8 ) + ( j as u8 ) + ( k as u8 ) + x + y + z +} + +fn parenthesized() { + value + ( /*test*/x as Field /*test*/ ) +} + +fn parenthesized() { + value + ( +// line + x as Field + ) +} + +fn constructor() { + Point{x :5, + y: 10 }; +} + +fn if_expr() { + if true { println("Hello :D"); } +} + +fn return_if_expr() { + if true { +42 +} +else +{ 40 + 2 } +} + +fn return_if_expr() { + if true {42}; + + if true { + 42 + } + else { + 40 + + 2 } +} + +fn if_if() { +(if cond { some(); } else { none(); }) + .bar() + .baz(); +} \ No newline at end of file diff --git a/tooling/nargo_fmt/tests/input/fn.nr b/tooling/nargo_fmt/tests/input/fn.nr new file mode 100644 index 00000000000..9e19222decb --- /dev/null +++ b/tooling/nargo_fmt/tests/input/fn.nr @@ -0,0 +1,75 @@ +fn main(x: pub u8, y: u8) {} + +fn main(x: pub u8, y: u8) -> pub Field {} + +fn main(x: A, y: B) -> pub Field where A: Eq, B: Eq {} + +fn main() +// hello +{} + +fn main( + // hello +) {} + +fn main( + // hello + unit: () +) {} + +fn main() where T: Eq {} + +fn main(tape: [Field; TAPE_LEN], initial_registers: [Field; REGISTER_COUNT], initial_memory: [Field; MEM_COUNT], initial_program_counter: Field, initial_call_stack: [Field; MAX_CALL_STACK], initial_call_stack_pointer: u64) -> pub ExecutionResult {} + +fn apply_binary_field_op(lhs: RegisterIndex, rhs: RegisterIndex, result: RegisterIndex, op: u8, registers: &mut Registers) -> bool {} + +fn main() -> pub [Field;2] {} + +fn ret_normal_lambda1() -> ((fn() -> Field)) {} + +fn ret_normal_lambda1() -> fn() -> Field {} + +fn ret_closure1() -> fn[(Field,)]() -> Field {} + +fn ret_closure2() -> fn[(Field,Field)]() -> Field {} + +fn ret_closure3() -> fn[(u32,u64)]() -> u64 {} + +fn make_counter() -> fn[(&mut Field,)]() -> Field {} + +fn get_some(generator: fn[Env]() -> Field) -> [Field;5] {} + +fn main( + message: [u8; 10], message_field: Field, pub_key_x: Field, pub_key_y: Field, signature: [u8; 64] +) {} + +pub fn from_baz(x: [Field; crate::foo::MAGIC_NUMBER]) {} + +fn id< T , let I : Field > ( x : [ Field ; I ] ) -> [Field; I ] { } + +fn id_two(x: [Field ; I]) -> [ Field; I] {} + +fn whitespace_before_generics < T > (foo: T) {} + +fn more_whitespace_before_generics < +T > (foo: T) {} + +fn with_unconstrained(x: unconstrained fn() -> ()) {} + +pub ( crate ) fn one() {} + +unconstrained pub fn two() {} + +unconstrained pub comptime fn two() {} + +/// Documented +#[test] fn three() {} + +#[test(should_fail)] +// comment +fn four() {} + +#[test(should_fail_with = "oops")] +fn five() {} + diff --git a/tooling/nargo_fmt/tests/input/for.nr b/tooling/nargo_fmt/tests/input/for.nr new file mode 100644 index 00000000000..bf0a497fe65 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/for.nr @@ -0,0 +1,28 @@ +fn for_stmt() { + for elem in self { + ret &= predicate(elem); + } +} + +fn for_stmt() { + for i in 0..(C1-1) { + + for _j in 1..(C1-i-1) { + + b *= b; + + } + + for k in 0 ..= C1 + { + d *= d; } + + z *= if b == 1 { 1 } else { c }; + + c *= c; + + t *= if b == 1 { 1 } else { c }; + + b = t; + } +} diff --git a/tooling/nargo_fmt/tests/input/global.nr b/tooling/nargo_fmt/tests/input/global.nr new file mode 100644 index 00000000000..bf023c61805 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/global.nr @@ -0,0 +1,17 @@ +//! Super module :] + +// super global variable +global answer = 42; + +// Super module :] + + + + + + + + + +// super global variable +global answer = 42; diff --git a/tooling/nargo_fmt/tests/input/if.nr b/tooling/nargo_fmt/tests/input/if.nr new file mode 100644 index 00000000000..be72eb79a18 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/if.nr @@ -0,0 +1,57 @@ +//@error_on_lost_comment=false +fn main() { + let (x,y) = if is_square(gx1) {(x1, sqrt(gx1))} else {(x2, sqrt(gx2))}; + + let n = if x != y { if x != 20 { slice.push_back(y) } else { slice } } else { slice }; + + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + 0 + } + else + { + 0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tooling/nargo_fmt/tests/input/ignore.nr b/tooling/nargo_fmt/tests/input/ignore.nr new file mode 100644 index 00000000000..7d5a187146b --- /dev/null +++ b/tooling/nargo_fmt/tests/input/ignore.nr @@ -0,0 +1,28 @@ +fn main() { + // noir-fmt:ignore + assert( x != y ); + assert( x != y ); + { + // noir-fmt:ignore + }; + assert( x != y ); +} +// noir-fmt:ignore +fn main() { +1; +2; +3; +} +// noir-fmt:ignore +mod items { +fn hello() {} +} + +fn mk_array() { + // noir-fmt:ignore + let array = [1, + ]; + let array = [1, + ]; +} + diff --git a/tooling/nargo_fmt/tests/input/impl.nr b/tooling/nargo_fmt/tests/input/impl.nr new file mode 100644 index 00000000000..dae62033a65 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/impl.nr @@ -0,0 +1,31 @@ +impl MyType {} + +impl MyType {} + +impl MyType {} + +impl MyType { + fn method(self) {} + + fn method(mut self) {} + + fn method(&mut self) {} + + fn method(self: Self) {} + + fn method(mut self: Self) {} +} + +impl MyType { +fn method(self) {} +} + +impl MyType { + fn method(self) {} +} + +impl MyStruct where T: MyEq { +fn my_eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.my_eq(other.b) + } +} 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..0647bbaa580 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/import_braces.nr @@ -0,0 +1 @@ +use std::hash::{sha256}; diff --git a/tooling/nargo_fmt/tests/input/index.nr b/tooling/nargo_fmt/tests/input/index.nr new file mode 100644 index 00000000000..7d10e897b8d --- /dev/null +++ b/tooling/nargo_fmt/tests/input/index.nr @@ -0,0 +1,10 @@ +fn foo() { + let arr = [10, 20, 30, 40]; + arr [2]; + arr [2]; + arr [/*test*/2]; + arr [2/*test*/]; + arr [ + // test + 2]; +} \ No newline at end of file diff --git a/tooling/nargo_fmt/tests/input/infix.nr b/tooling/nargo_fmt/tests/input/infix.nr new file mode 100644 index 00000000000..059e58c6b64 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/infix.nr @@ -0,0 +1,13 @@ +//@error_on_lost_comment=false +fn foo() { + 40 + 2; + !40+2; + 40 + 2 == 42; + +40/*test*/ + 2 == 42; + 40 + 2/*test*/ == 42; +} + +fn big() { + assert(bjj_affine.contains(bjj_affine.gen) & bjj_affine.contains(p1_affine) & bjj_affine.contains(p2_affine) & bjj_affine.contains(p3_affine) & bjj_affine.contains(p4_affine) & bjj_affine.contains(p5_affine)); +} diff --git a/tooling/nargo_fmt/tests/input/let.nr b/tooling/nargo_fmt/tests/input/let.nr new file mode 100644 index 00000000000..16ce0a9d7f1 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/let.nr @@ -0,0 +1,35 @@ +//@error_on_lost_comment=false +fn let_() { + let fn_call = my_function(some_function( 10, "arg1", another_function() ),another_func (20, some_function() , 30 )); + let array = [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]]; + + let padded_sha256_hash: [u8; 259] = [ + // Padded hash + 209, 50, 135, 178, 4, 155, 190, 229, 228, 111, 61, 174, 8, 49, 48, 116, 90, 226, 77, 7, 111, 27, 19, 113, 154, 48, 138, 136, 138, 15, 230, 132, 32, 4, 0, 5, 1, 2, 4, 3, 101, 1, 72, 134, 96, 9, 6, 13, 48, 49, + 48, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, + // Rest is padded with 0s until max bytes + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ]; + + let a = BigUint56 {limbs:[1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}; + + let person = Person { first_name: "John", last_name: "Doe", home_address: Address { street: "123 Main St", city: "Exampleville", zip_code: "12345" } }; + + let person = Person { first_name: "John", last_name: "Doe", home_address: Address { street: "123 Main St", city: "Exampleville", zip_code: "12345", master: Person { first_name: "John", last_name: "Doe", home_address: Address { street: "123 Main St", city: "Exampleville", zip_code: "12345" } } } }; + + let expr = MyExpr {// A boolean literal (true, false). +kind: ExprKind::Bool(true), + }; + + let expr = MyExpr {/*A boolean literal (true, false).*/kind: ExprKind::Bool(true),}; + + let mut V = crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct {}; + let mut V = crate2::MyStruct {/*test*/}; + let mut V = crate2::MyStruct { + // sad + }; +} diff --git a/tooling/nargo_fmt/tests/input/literals.nr b/tooling/nargo_fmt/tests/input/literals.nr new file mode 100644 index 00000000000..fbdc7676845 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/literals.nr @@ -0,0 +1,25 @@ +//@error_on_lost_comment=false +fn main() { + [1,2,3,4,5]; + + + [1;5]; + + [0xff;5]; + + [0 as u8; MAX_BYTES]; + + true; + + "hello world"; + + "hell\0\"world"; + + f"i: {i}, j: {j}"; + + ( ); + + (/*test*/); + + () +} diff --git a/tooling/nargo_fmt/tests/input/member_access.nr b/tooling/nargo_fmt/tests/input/member_access.nr new file mode 100644 index 00000000000..abcab671836 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/member_access.nr @@ -0,0 +1,15 @@ +struct Address { + city: String, + country: String, +} + +struct Person { + name: String, + age: u8, + address: Address, +} + +fn foo(p: Person) { + p . name; + p.address . country; +} diff --git a/tooling/nargo_fmt/tests/input/method_call.nr b/tooling/nargo_fmt/tests/input/method_call.nr new file mode 100644 index 00000000000..175647b4650 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/method_call.nr @@ -0,0 +1,3 @@ +fn foo() { + my_object . some_method( 10,var_value,inner_method( 20 , 30) ); +} diff --git a/tooling/nargo_fmt/tests/input/module.nr b/tooling/nargo_fmt/tests/input/module.nr new file mode 100644 index 00000000000..3e01b81bcf0 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/module.nr @@ -0,0 +1,39 @@ +#![inner] +#![inner2] + +mod a { + mod b { + struct Data { + a: Field + } + } + + fn data(a: Field) -> Data { + Data { a } + } + + fn data2(a: Field) -> Data2 { + Data2 { a } + } + + #[custom] + #[another_custom] + mod tests { + #[test] + fn test() { + data(1); + data2(1); + } + } + + #[attr] + mod baz; + + mod empty { + #![inner] + } +} + +pub(crate) mod one { } + +pub mod two { } diff --git a/tooling/nargo_fmt/tests/input/nested_if_else.nr b/tooling/nargo_fmt/tests/input/nested_if_else.nr new file mode 100644 index 00000000000..8aa120e3b18 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/nested_if_else.nr @@ -0,0 +1,3 @@ +fn nested_if_else() { + if false { 1 } else if false { 2 } else { 3 } +} diff --git a/tooling/nargo_fmt/tests/input/nested_parens.nr b/tooling/nargo_fmt/tests/input/nested_parens.nr new file mode 100644 index 00000000000..53eaa63c279 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/nested_parens.nr @@ -0,0 +1,5 @@ +//@remove_nested_parens=false +fn main() { + ((())); + ((((((((())))))))); +} diff --git a/tooling/nargo_fmt/tests/input/parens.nr b/tooling/nargo_fmt/tests/input/parens.nr new file mode 100644 index 00000000000..769b477a34d --- /dev/null +++ b/tooling/nargo_fmt/tests/input/parens.nr @@ -0,0 +1,53 @@ +fn main(x : u64, y : pub u64) { + ( +// +1 + ); + +( +// a +1 +// b +); + +( +// test + 1 + ); + + ( +// 1 +( +// 2 + 2 +) +); + + ( + + /*a*/ + + ( + + // test + 1 + ) + /*b*/ +); + + ( + // test + 1 + ); + + ( /*a*/ 1 ); + + ( 1 /*b*/ ); + + ( /*c*/ 1 /*d*/ ); + + ( /*test*/ 1 /*test 2*/ ); + + ((())); + (((((((((((((((()))))))))))))))); +} diff --git a/tooling/nargo_fmt/tests/input/print.nr b/tooling/nargo_fmt/tests/input/print.nr new file mode 100644 index 00000000000..d8404f674b0 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/print.nr @@ -0,0 +1,4 @@ +fn main() { + std::print("Hello world"); + std::println("Hello world"); +} diff --git a/tooling/nargo_fmt/tests/input/print2.nr b/tooling/nargo_fmt/tests/input/print2.nr new file mode 100644 index 00000000000..d8404f674b0 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/print2.nr @@ -0,0 +1,4 @@ +fn main() { + std::print("Hello world"); + std::println("Hello world"); +} diff --git a/tooling/nargo_fmt/tests/input/read_array.nr b/tooling/nargo_fmt/tests/input/read_array.nr new file mode 100644 index 00000000000..d2619884b5d --- /dev/null +++ b/tooling/nargo_fmt/tests/input/read_array.nr @@ -0,0 +1,6 @@ +fn read_array(x: [Field; 3]) { + assert(x[0] == 1); + let y = [1, 5, 27]; + + assert(y[x[0]] == 5); +} diff --git a/tooling/nargo_fmt/tests/input/single_fn.nr b/tooling/nargo_fmt/tests/input/single_fn.nr new file mode 100644 index 00000000000..c7ee3bbd3aa --- /dev/null +++ b/tooling/nargo_fmt/tests/input/single_fn.nr @@ -0,0 +1,3 @@ +fn main() { + // hello +} \ No newline at end of file diff --git a/tooling/nargo_fmt/tests/input/single_mod.nr b/tooling/nargo_fmt/tests/input/single_mod.nr new file mode 100644 index 00000000000..f02dbfb5464 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/single_mod.nr @@ -0,0 +1 @@ +mod hello {} \ No newline at end of file diff --git a/tooling/nargo_fmt/tests/input/singleton_import.nr b/tooling/nargo_fmt/tests/input/singleton_import.nr new file mode 100644 index 00000000000..bb1bad500d9 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/singleton_import.nr @@ -0,0 +1,2 @@ +use dep::std; +use some_crate; diff --git a/tooling/nargo_fmt/tests/input/struct.nr b/tooling/nargo_fmt/tests/input/struct.nr new file mode 100644 index 00000000000..2e5fff47f9e --- /dev/null +++ b/tooling/nargo_fmt/tests/input/struct.nr @@ -0,0 +1,77 @@ +struct Foo { + bar: Field, + array: [Field; 2], +} + +struct Pair { + first: Foo, + pub second: Field, +} + +impl Foo { + fn default(x: Field,y: Field) -> Self { + Self { bar: 0, array: [x,y] } + } +} + +impl Pair { + fn foo(p: Self) -> Foo { + p.first + } + + fn bar(self) -> Field { + self.foo().bar + } +} + +struct Nested { + a: Field, + b: Field +} +struct MyStruct { + my_bool: bool, + my_int: u32, + my_nest: Nested, +} +fn test_struct_in_tuple(a_bool : bool,x:Field, y:Field) -> (MyStruct, bool) { + let my_struct = MyStruct { + my_bool: a_bool, + my_int: 5, + my_nest: Nested{a:x,b:y}, + }; + (my_struct, a_bool) +} + +struct Animal { + legs: Field, + eyes: u8, +} + +fn get_dog() -> Animal { + let dog = Animal { legs: 4, eyes: 2 }; + dog +} + +fn main(x: Field, y: Field) { + let first = Foo::default(x,y); + let p = Pair { first, second: 1 }; + + assert(p.bar() == x); + assert(p.second == y); + assert(p.first.array[0] != p.first.array[1]); + + // Nested structs + let (struct_from_tuple, a_bool) = test_struct_in_tuple(true,x,y); + assert(struct_from_tuple.my_bool == true); + assert(a_bool == true); + assert(struct_from_tuple.my_int == 5); + assert(struct_from_tuple.my_nest.a == 0); + + // Regression test for issue #670 + let Animal { legs, eyes } = get_dog(); + let six = legs + eyes as Field; + + assert(six == 6); + + let Animal { legs: _, eyes: _ } = get_dog(); +} diff --git a/tooling/nargo_fmt/tests/input/submodule.nr b/tooling/nargo_fmt/tests/input/submodule.nr new file mode 100644 index 00000000000..d5b162fd28d --- /dev/null +++ b/tooling/nargo_fmt/tests/input/submodule.nr @@ -0,0 +1,25 @@ +mod a { +// hello +} + +mod a { +// hello + mod b { +// hello + } +} + +mod a {mod b {mod c {}}} + +mod a { +// 1 +// 2 +// 3 +/*test*/ +} + +mod a { + /**/ mod b { + mod c {} + } +} diff --git a/tooling/nargo_fmt/tests/input/trait.nr b/tooling/nargo_fmt/tests/input/trait.nr new file mode 100644 index 00000000000..0467585fac3 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/trait.nr @@ -0,0 +1,2 @@ +trait Foo: Bar + Baz {} + diff --git a/tooling/nargo_fmt/tests/input/trait_alias.nr b/tooling/nargo_fmt/tests/input/trait_alias.nr new file mode 100644 index 00000000000..53ae756795b --- /dev/null +++ b/tooling/nargo_fmt/tests/input/trait_alias.nr @@ -0,0 +1,78 @@ +trait Foo { + fn foo(self) -> Self; +} + +trait Baz = Foo; + +impl Foo for Field { + fn foo(self) -> Self { self } +} + +fn baz(x: T) -> T where T: Baz { + x.foo() +} + + +pub trait Foo_2 { + fn foo_2(self) -> Self; +} + +pub trait Bar_2 { + fn bar_2(self) -> Self; +} + +pub trait Baz_2 = Foo_2 + Bar_2; + +fn baz_2(x: T) -> T where T: Baz_2 { + x.foo_2().bar_2() +} + +impl Foo_2 for Field { + fn foo_2(self) -> Self { + self + 1 + } +} + +impl Bar_2 for Field { + fn bar_2(self) -> Self { + self + 2 + } +} + + +trait Foo_3 { + fn foo_3(self) -> Self; +} + +trait Bar_3 { + fn bar_3(self) -> T; +} + +trait Baz_3 = Foo_3 + Bar_3; + +fn baz_3(x: T) -> U where T: Baz_3 { + x.foo_3().bar_3() +} + +impl Foo_3 for Field { + fn foo_3(self) -> Self { + self + 1 + } +} + +impl Bar_3 for Field { + fn bar_3(self) -> bool { + true + } +} + + +fn main() { + let x: Field = 0; + let _ = baz(x); + + assert(0.foo_2().bar_2() == baz_2(0)); + + assert(0.foo_3().bar_3() == baz_3(0)); +} + diff --git a/tooling/nargo_fmt/tests/input/tuple.nr b/tooling/nargo_fmt/tests/input/tuple.nr new file mode 100644 index 00000000000..5be07be6ff4 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/tuple.nr @@ -0,0 +1,47 @@ +fn main() { +(1,); +( +// hello +1,); +(/*hello*/1,); +(1,/*hello*/); + ( 1, ); +( /*test*/1, ); +( /*a*/1/*b*/, ); +( /*a*/1/*b*/, /*c*/2/*d*/, /*c*/2/*d*/ ); +( /*a*/1/*b*/, /*c*/2/*d*/, /*c*/2/*d*/, /*e*/3/*f*/ ); + +( 1 /*1*/ , 2 /* 2*/ ); + + + + +( 1, /*test*/ ); + + ( +// +1, +); + +( +// 1 +1, +// 2, +2, +); + +(/*1*/1, /*2*/2); + +((( +//2 +1,),),); +( + /*a*/ + 1 + /*b*/, +/*c*/ +2/*d*/, +/*c*/2/*d*/, +/*e*/3/*f*/ +); +} 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_fmt/tests/input/unary_operators.nr b/tooling/nargo_fmt/tests/input/unary_operators.nr new file mode 100644 index 00000000000..4324b8045cc --- /dev/null +++ b/tooling/nargo_fmt/tests/input/unary_operators.nr @@ -0,0 +1,10 @@ +//@error_on_lost_comment=false +fn main() { + -1; +-/*test*/1; + -/*test*/1; + + & mut 1; + * v; + * * * v; +} \ No newline at end of file diff --git a/tooling/nargo_fmt/tests/input/unsafe.nr b/tooling/nargo_fmt/tests/input/unsafe.nr new file mode 100644 index 00000000000..0aeffd0b983 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/unsafe.nr @@ -0,0 +1,11 @@ +fn main(x: pub u8, y: u8) { + /// Safety: testing + unsafe { + } + + /// Safety: testing + unsafe { + assert_eq(x, y); + } +} + diff --git a/tooling/nargo_fmt/tests/input/use_super.nr b/tooling/nargo_fmt/tests/input/use_super.nr new file mode 100644 index 00000000000..a3b7d4cb4e2 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/use_super.nr @@ -0,0 +1,7 @@ +fn some_func() { + +} + +mod foo { + use super::some_func; +} diff --git a/tooling/nargo_fmt/tests/input/vec.nr b/tooling/nargo_fmt/tests/input/vec.nr new file mode 100644 index 00000000000..1c9a791961e --- /dev/null +++ b/tooling/nargo_fmt/tests/input/vec.nr @@ -0,0 +1,60 @@ +struct Vec { + slice: [T] +} + +// A mutable vector type implemented as a wrapper around immutable slices. +// A separate type is technically not needed but helps differentiate which operations are mutable. +impl Vec { + pub fn new() -> Self { + Self { slice: [] } + } + + // Create a Vec containing each element from the given slice. + // Mutations to the resulting Vec will not affect the original slice. + pub fn from_slice(slice: [T]) -> Self { + Self { slice } + } + + /// 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: Field) -> T { + self.slice[index] + } + + /// Push a new element to the end of the vector, returning a + /// new vector with a length one greater than the + /// original unmodified vector. + pub fn push(&mut self, elem: T) { + self.slice = self.slice.push_back(elem); + } + + /// Pop an element from the end of the given vector, returning + /// a new vector with a length of one less than the given vector, + /// as well as the popped element. + /// Panics if the given vector's length is zero. + pub fn pop(&mut self) -> T { + let (popped_slice, last_elem) = self.slice.pop_back(); + self.slice = popped_slice; + last_elem + } + + /// Insert an element at a specified index, shifting all elements + /// after it to the right + pub fn insert(&mut self, index: Field, 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: Field) -> 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) -> Field { + self.slice.len() + } +} diff --git a/tooling/nargo_toml/Cargo.toml b/tooling/nargo_toml/Cargo.toml new file mode 100644 index 00000000000..f5f7d7cd595 --- /dev/null +++ b/tooling/nargo_toml/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "nargo_toml" +description = "Utilities for working with Nargo.toml files" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[lints] +workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +dirs.workspace = true +fm.workspace = true +nargo.workspace = true +noirc_frontend.workspace = true +serde.workspace = true +thiserror.workspace = true +toml.workspace = true +url.workspace = true +noirc_driver.workspace = true +semver = "1.0.20" + +[dev-dependencies] +tempfile.workspace = true +test-case.workspace = true diff --git a/tooling/nargo_toml/src/errors.rs b/tooling/nargo_toml/src/errors.rs new file mode 100644 index 00000000000..7e1003d04f7 --- /dev/null +++ b/tooling/nargo_toml/src/errors.rs @@ -0,0 +1,95 @@ +use std::path::PathBuf; + +use nargo::package::PackageType; +use noirc_frontend::graph::CrateName; +use thiserror::Error; + +/// Errors covering situations where a package is either missing, malformed or does not pass semver +/// validation checks. +#[derive(Debug, Error)] +pub enum ManifestError { + /// Package doesn't have a manifest file + #[error("cannot find a Nargo.toml for {0}")] + MissingFile(PathBuf), + + #[error("Cannot read file {0} - does it exist?")] + ReadFailed(PathBuf), + + #[error("Nargo.toml is missing a parent directory")] + MissingParent, + + #[error("Missing `type` field in {0}")] + MissingPackageType(PathBuf), + + #[error("Cannot use `{1}` for `type` field in {0}")] + InvalidPackageType(PathBuf, String), + + /// Package manifest is unreadable. + #[error("Nargo.toml is badly formed, could not parse.\n\n {0}")] + MalformedFile(#[from] toml::de::Error), + + #[error("Unexpected workspace definition found in {0}. If you're attempting to load this as a dependency, you may need to add a `directory` field to your `Nargo.toml` to show which package within the workspace to use")] + UnexpectedWorkspace(PathBuf), + + #[error("Cannot find file {entry} which was specified as the `entry` field in {toml}")] + MissingEntryFile { toml: PathBuf, entry: PathBuf }, + + #[error( + r#"Cannot find file {entry} which is defaulted due to specifying `type = "{package_type}"` in {toml}"# + )] + MissingDefaultEntryFile { toml: PathBuf, entry: PathBuf, package_type: PackageType }, + + #[error("{} found in {toml}", if name.is_empty() { "Empty package name".into() } else { format!("Invalid package name `{name}`") })] + InvalidPackageName { toml: PathBuf, name: String }, + + #[error("{} found in {toml}", if name.is_empty() { "Empty dependency name".into() } else { format!("Invalid dependency name `{name}`") })] + InvalidDependencyName { toml: PathBuf, name: String }, + + #[error("Invalid directory path {directory} in {toml}: It must point to a subdirectory")] + InvalidDirectory { toml: PathBuf, directory: PathBuf }, + + /// Encountered error while downloading git repository. + #[error("{0}")] + GitError(String), + + #[error("Selected package `{0}` was not found")] + MissingSelectedPackage(CrateName), + + #[error("Default package was not found. Does {0} exist in your workspace?")] + MissingDefaultPackage(PathBuf), + + #[error("Package `{0}` has type `bin` but you cannot depend on binary packages")] + BinaryDependency(CrateName), + + #[error("Missing `name` field in {toml}")] + MissingNameField { toml: PathBuf }, + + #[error("No common ancestor between {root} and {current}")] + NoCommonAncestor { root: PathBuf, current: PathBuf }, + + #[error(transparent)] + SemverError(SemverError), + + #[error("Cyclic package dependency found when processing {cycle}")] + CyclicDependency { cycle: String }, + + #[error("Failed to parse expression width with the following error: {0}")] + ParseExpressionWidth(String), +} + +#[allow(clippy::enum_variant_names)] +#[derive(Error, Debug, PartialEq, Eq, Clone)] +pub enum SemverError { + #[error("Invalid value for `compiler_version` in package {package_name}. Requirements may only refer to full releases")] + InvalidCompilerVersionRequirement { package_name: CrateName, required_compiler_version: String }, + #[error("Incompatible compiler version in package {package_name}. Required compiler version is {required_compiler_version} but the compiler version is {compiler_version_found}.\n Update the compiler_version field in Nargo.toml to >={required_compiler_version} or compile this project with version {required_compiler_version}")] + IncompatibleVersion { + package_name: CrateName, + required_compiler_version: String, + compiler_version_found: String, + }, + #[error("Could not parse the required compiler version for package {package_name} in Nargo.toml. Error: {error}")] + CouldNotParseRequiredVersion { package_name: String, error: String }, + #[error("Could not parse the package version for package {package_name} in Nargo.toml. Error: {error}")] + CouldNotParsePackageVersion { package_name: String, error: String }, +} diff --git a/tooling/nargo_toml/src/git.rs b/tooling/nargo_toml/src/git.rs new file mode 100644 index 00000000000..efaed4fabb9 --- /dev/null +++ b/tooling/nargo_toml/src/git.rs @@ -0,0 +1,75 @@ +use std::path::PathBuf; + +/// Creates a unique folder name for a GitHub repo +/// by using its URL and tag +fn resolve_folder_name(base: &url::Url, tag: &str) -> String { + let mut folder = PathBuf::from(""); + for part in [base.domain().unwrap(), base.path(), tag] { + folder.push(part.trim_start_matches('/')); + } + folder.to_string_lossy().into_owned() +} + +/// Path to the `nargo` directory under `$HOME`. +fn nargo_crates() -> PathBuf { + dirs::home_dir().unwrap().join("nargo") +} + +/// Target directory to download dependencies into, e.g. +/// `$HOME/nargo/github.com/noir-lang/noir-bignum/v0.1.2` +fn git_dep_location(base: &url::Url, tag: &str) -> PathBuf { + let folder_name = resolve_folder_name(base, tag); + + nargo_crates().join(folder_name) +} + +/// XXX: I'd prefer to use a GitHub library however, there +/// does not seem to be an easy way to download a repo at a specific +/// tag +/// github-rs looks promising, however it seems to require an API token +/// +/// One advantage of using "git clone" is that there is effectively no rate limit +pub(crate) fn clone_git_repo(url: &str, tag: &str) -> Result { + use std::process::Command; + + let base = match url::Url::parse(url) { + Ok(base) => base, + Err(err) => return Err(err.to_string()), + }; + + let loc = git_dep_location(&base, tag); + if loc.exists() { + return Ok(loc); + } + + Command::new("git") + .arg("-c") + .arg("advice.detachedHead=false") + .arg("clone") + .arg("--depth") + .arg("1") + .arg("--branch") + .arg(tag) + .arg(base.as_str()) + .arg(&loc) + .status() + .expect("git clone command failed to start"); + + Ok(loc) +} + +#[cfg(test)] +mod tests { + use test_case::test_case; + use url::Url; + + use super::resolve_folder_name; + + #[test_case("https://github.com/noir-lang/noir-bignum/"; "with slash")] + #[test_case("https://github.com/noir-lang/noir-bignum"; "without slash")] + fn test_resolve_folder_name(url: &str) { + let tag = "v0.4.2"; + let dir = resolve_folder_name(&Url::parse(url).unwrap(), tag); + assert_eq!(dir, "github.com/noir-lang/noir-bignum/v0.4.2"); + } +} diff --git a/tooling/nargo_toml/src/lib.rs b/tooling/nargo_toml/src/lib.rs new file mode 100644 index 00000000000..fa556d445a4 --- /dev/null +++ b/tooling/nargo_toml/src/lib.rs @@ -0,0 +1,725 @@ +#![forbid(unsafe_code)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] +#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] + +use std::{ + collections::BTreeMap, + path::{Component, Path, PathBuf}, +}; + +use errors::SemverError; +use fm::{NormalizePath, FILE_EXTENSION}; +use nargo::{ + package::{Dependency, Package, PackageType}, + workspace::Workspace, +}; +use noirc_driver::parse_expression_width; +use noirc_frontend::graph::CrateName; +use serde::Deserialize; + +mod errors; +mod git; +mod semver; + +pub use errors::ManifestError; +use git::clone_git_repo; + +/// Searches for a `Nargo.toml` file in the current directory and all parent directories. +/// For example, if the current directory is `/workspace/package/src`, then this function +/// will search for a `Nargo.toml` file in +/// * `/workspace/package/src`, +/// * `/workspace/package`, +/// * `/workspace`. +/// +/// Returns the [PathBuf] of the `Nargo.toml` file if found, otherwise returns None. +/// +/// It will return innermost `Nargo.toml` file, which is the one closest to the current directory. +/// For example, if the current directory is `/workspace/package/src`, then this function +/// will return the `Nargo.toml` file in `/workspace/package/Nargo.toml` +pub fn find_file_manifest(current_path: &Path) -> Option { + for path in current_path.ancestors() { + if let Ok(toml_path) = get_package_manifest(path) { + return Some(toml_path); + } + } + None +} + +/// Returns the [PathBuf] of the directory containing the `Nargo.toml` by searching from `current_path` to the root of its [Path]. +/// When `workspace` is `true` it returns the topmost directory, when `false` the innermost one. +/// +/// Returns a [ManifestError] if no parent directories of `current_path` contain a manifest file. +pub fn find_root(current_path: &Path, workspace: bool) -> Result { + if workspace { + find_package_root(current_path) + } else { + find_file_root(current_path) + } +} + +/// Returns the [PathBuf] of the directory containing the `Nargo.toml` by searching from `current_path` to the root of its [Path], +/// returning at the innermost directory found, i.e. the one corresponding to the package that contains the `current_path`. +/// +/// Returns a [ManifestError] if no parent directories of `current_path` contain a manifest file. +pub fn find_file_root(current_path: &Path) -> Result { + match find_file_manifest(current_path) { + Some(manifest_path) => { + let package_root = manifest_path + .parent() + .expect("infallible: manifest file path can't be root directory"); + Ok(package_root.to_path_buf()) + } + None => Err(ManifestError::MissingFile(current_path.to_path_buf())), + } +} + +/// Returns the [PathBuf] of the directory containing the `Nargo.toml` by searching from `current_path` to the root of its [Path], +/// returning at the topmost directory found, i.e. the one corresponding to the entire workspace. +/// +/// Returns a [ManifestError] if no parent directories of `current_path` contain a manifest file. +pub fn find_package_root(current_path: &Path) -> Result { + let root = path_root(current_path); + let manifest_path = find_package_manifest(&root, current_path)?; + + let package_root = + manifest_path.parent().expect("infallible: manifest file path can't be root directory"); + + Ok(package_root.to_path_buf()) +} + +// TODO(#2323): We are probably going to need a "filepath utils" crate soon +/// Get the root of path, for example: +/// * `C:\foo\bar` -> `C:\foo` +/// * `//shared/foo/bar` -> `//shared/foo` +/// * `/foo` -> `/foo` +/// otherwise empty path. +fn path_root(path: &Path) -> PathBuf { + let mut components = path.components(); + + match (components.next(), components.next()) { + // Preserve prefix if one exists + (Some(prefix @ Component::Prefix(_)), Some(root @ Component::RootDir)) => { + PathBuf::from(prefix.as_os_str()).join(root.as_os_str()) + } + (Some(root @ Component::RootDir), _) => PathBuf::from(root.as_os_str()), + _ => PathBuf::new(), + } +} + +/// Returns the [PathBuf] of the `Nargo.toml` file by searching from `current_path` and stopping at `root_path`. +/// +/// Returns a [ManifestError] if no parent directories of `current_path` contain a manifest file. +pub fn find_package_manifest( + root_path: &Path, + current_path: &Path, +) -> Result { + if current_path.starts_with(root_path) { + let mut found_toml_paths = Vec::new(); + for path in current_path.ancestors() { + if let Ok(toml_path) = get_package_manifest(path) { + found_toml_paths.push(toml_path); + } + // While traversing, break once we process the root specified + if path == root_path { + break; + } + } + + // Return the shallowest Nargo.toml, which will be the last in the list + found_toml_paths.pop().ok_or_else(|| ManifestError::MissingFile(current_path.to_path_buf())) + } else { + Err(ManifestError::NoCommonAncestor { + root: root_path.to_path_buf(), + current: current_path.to_path_buf(), + }) + } +} + +/// Returns the [PathBuf] of the `Nargo.toml` file in the `current_path` directory. +/// +/// Returns a [ManifestError] if `current_path` does not contain a manifest file. +pub fn get_package_manifest(current_path: &Path) -> Result { + let toml_path = current_path.join("Nargo.toml"); + if toml_path.exists() { + Ok(toml_path) + } else { + Err(ManifestError::MissingFile(current_path.to_path_buf())) + } +} + +#[derive(Debug, Deserialize, Clone)] +struct PackageConfig { + package: PackageMetadata, + #[serde(default)] + dependencies: BTreeMap, +} + +impl PackageConfig { + fn resolve_to_package( + &self, + root_dir: &Path, + processed: &mut Vec, + ) -> Result { + let name: CrateName = if let Some(name) = &self.package.name { + name.parse().map_err(|_| ManifestError::InvalidPackageName { + toml: root_dir.join("Nargo.toml"), + name: name.into(), + })? + } else { + return Err(ManifestError::MissingNameField { toml: root_dir.join("Nargo.toml") }); + }; + + let mut dependencies: BTreeMap = BTreeMap::new(); + for (name, dep_config) in self.dependencies.iter() { + let name = name.parse().map_err(|_| ManifestError::InvalidDependencyName { + toml: root_dir.join("Nargo.toml"), + name: name.into(), + })?; + let resolved_dep = dep_config.resolve_to_dependency(root_dir, processed)?; + + dependencies.insert(name, resolved_dep); + } + + let package_type = match self.package.package_type.as_deref() { + Some("lib") => PackageType::Library, + Some("bin") => PackageType::Binary, + Some("contract") => PackageType::Contract, + Some(invalid) => { + return Err(ManifestError::InvalidPackageType( + root_dir.join("Nargo.toml"), + invalid.to_string(), + )) + } + None => return Err(ManifestError::MissingPackageType(root_dir.join("Nargo.toml"))), + }; + + let entry_path = if let Some(entry_path) = &self.package.entry { + let custom_entry_path = root_dir.join(entry_path); + if custom_entry_path.exists() { + custom_entry_path + } else { + return Err(ManifestError::MissingEntryFile { + toml: root_dir.join("Nargo.toml"), + entry: custom_entry_path, + }); + } + } else { + let default_entry_path = match package_type { + PackageType::Library => { + root_dir.join("src").join("lib").with_extension(FILE_EXTENSION) + } + PackageType::Binary | PackageType::Contract => { + root_dir.join("src").join("main").with_extension(FILE_EXTENSION) + } + }; + + if default_entry_path.exists() { + default_entry_path + } else { + return Err(ManifestError::MissingDefaultEntryFile { + toml: root_dir.join("Nargo.toml"), + entry: default_entry_path, + package_type, + }); + } + }; + + // If there is a package version, ensure that it is semver compatible + if let Some(version) = &self.package.version { + semver::parse_semver_compatible_version(version).map_err(|err| { + ManifestError::SemverError(SemverError::CouldNotParsePackageVersion { + package_name: name.to_string(), + error: err.to_string(), + }) + })?; + } + + let expression_width = self + .package + .expression_width + .as_ref() + .map(|expression_width| { + parse_expression_width(expression_width) + .map_err(|err| ManifestError::ParseExpressionWidth(err.to_string())) + }) + .map_or(Ok(None), |res| res.map(Some))?; + + Ok(Package { + version: self.package.version.clone(), + compiler_required_version: self.package.compiler_version.clone(), + root_dir: root_dir.to_path_buf(), + entry_path, + package_type, + name, + dependencies, + expression_width, + }) + } +} + +/// Contains all the information about a package, as loaded from a `Nargo.toml`. +#[derive(Debug, Deserialize, Clone)] +#[serde(untagged)] +enum Config { + /// Represents a `Nargo.toml` with package fields. + Package { + #[serde(flatten)] + package_config: PackageConfig, + }, + /// Represents a `Nargo.toml` with workspace fields. + Workspace { + #[serde(alias = "workspace")] + workspace_config: WorkspaceConfig, + }, +} + +impl TryFrom for Config { + type Error = toml::de::Error; + + fn try_from(toml: String) -> Result { + toml::from_str(&toml) + } +} + +impl TryFrom<&str> for Config { + type Error = toml::de::Error; + + fn try_from(toml: &str) -> Result { + toml::from_str(toml) + } +} + +/// Tracks the root_dir of a `Nargo.toml` and the contents inside the file. +struct NargoToml { + root_dir: PathBuf, + config: Config, +} + +#[derive(Default, Debug, Deserialize, Clone)] +#[serde(rename_all = "kebab-case")] +struct WorkspaceConfig { + /// List of members in this workspace. + members: Vec, + /// Specifies the default crate to interact with in the context (similarly to how we have nargo as the default crate in this repository). + default_member: Option, +} + +#[allow(dead_code)] +#[derive(Default, Debug, Deserialize, Clone)] +struct PackageMetadata { + name: Option, + version: Option, + #[serde(alias = "type")] + package_type: Option, + entry: Option, + description: Option, + authors: Option>, + // If no compiler version is supplied, the latest is used + // For now, we state that all packages must be compiled under the same + // compiler version. + // We also state that ACIR and the compiler will upgrade in lockstep. + // so you will not need to supply an ACIR and compiler version + compiler_version: Option, + license: Option, + expression_width: Option, +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(untagged)] +/// Enum representing the different types of ways to +/// supply a source for the dependency +enum DependencyConfig { + Github { git: String, tag: String, directory: Option }, + Path { path: String }, +} + +impl DependencyConfig { + fn resolve_to_dependency( + &self, + pkg_root: &Path, + processed: &mut Vec, + ) -> Result { + let dep = match self { + Self::Github { git, tag, directory } => { + let dir_path = clone_git_repo(git, tag).map_err(ManifestError::GitError)?; + let project_path = if let Some(directory) = directory { + let internal_path = dir_path.join(directory).normalize(); + if !internal_path.starts_with(&dir_path) { + return Err(ManifestError::InvalidDirectory { + toml: pkg_root.join("Nargo.toml"), + directory: directory.into(), + }); + } + internal_path + } else { + dir_path + }; + let toml_path = project_path.join("Nargo.toml"); + let package = resolve_package_from_toml(&toml_path, processed)?; + Dependency::Remote { package } + } + Self::Path { path } => { + let dir_path = pkg_root.join(path); + let toml_path = dir_path.join("Nargo.toml"); + let package = resolve_package_from_toml(&toml_path, processed)?; + Dependency::Local { package } + } + }; + + // Cannot depend on a binary + // TODO: Can we depend upon contracts? + if dep.is_binary() { + Err(ManifestError::BinaryDependency(dep.package_name().clone())) + } else { + Ok(dep) + } + } +} + +fn toml_to_workspace( + nargo_toml: NargoToml, + package_selection: PackageSelection, +) -> Result { + let mut resolved = Vec::new(); + let workspace = match nargo_toml.config { + Config::Package { package_config } => { + let member = package_config.resolve_to_package(&nargo_toml.root_dir, &mut resolved)?; + match &package_selection { + PackageSelection::Selected(selected_name) if selected_name != &member.name => { + return Err(ManifestError::MissingSelectedPackage(member.name)) + } + _ => Workspace { + root_dir: nargo_toml.root_dir, + selected_package_index: Some(0), + members: vec![member], + is_assumed: false, + }, + } + } + Config::Workspace { workspace_config } => { + let mut members = Vec::new(); + let mut selected_package_index = None; + for (index, member_path) in workspace_config.members.into_iter().enumerate() { + let package_root_dir = nargo_toml.root_dir.join(&member_path); + let package_toml_path = package_root_dir.join("Nargo.toml"); + let member = resolve_package_from_toml(&package_toml_path, &mut resolved)?; + + match &package_selection { + PackageSelection::Selected(selected_name) => { + if &member.name == selected_name { + selected_package_index = Some(index); + } + } + PackageSelection::DefaultOrAll => { + if Some(&member_path) == workspace_config.default_member.as_ref() { + selected_package_index = Some(index); + } + } + PackageSelection::All => selected_package_index = None, + } + + members.push(member); + } + + // If the selected_package_index is still `None` but we have see a default_member or selected package, + // we want to present an error to users + match package_selection { + PackageSelection::Selected(selected_name) => { + if selected_package_index.is_none() { + return Err(ManifestError::MissingSelectedPackage(selected_name)); + } + } + PackageSelection::DefaultOrAll => match workspace_config.default_member { + // If `default-member` is specified but we don't have a selected_package_index, we need to fail + Some(default_path) if selected_package_index.is_none() => { + return Err(ManifestError::MissingDefaultPackage(default_path)); + } + // However, if there wasn't a `default-member`, we select All, so no error is needed + _ => (), + }, + PackageSelection::All => (), + } + + Workspace { + root_dir: nargo_toml.root_dir, + members, + selected_package_index, + is_assumed: false, + } + } + }; + + Ok(workspace) +} + +fn read_toml(toml_path: &Path) -> Result { + let toml_path = toml_path.normalize(); + let toml_as_string = std::fs::read_to_string(&toml_path) + .map_err(|_| ManifestError::ReadFailed(toml_path.to_path_buf()))?; + let root_dir = toml_path.parent().ok_or(ManifestError::MissingParent)?; + let nargo_toml = + NargoToml { root_dir: root_dir.to_path_buf(), config: toml_as_string.try_into()? }; + + Ok(nargo_toml) +} + +/// Resolves a Nargo.toml file into a `Package` struct as defined by our `nargo` core. +fn resolve_package_from_toml( + toml_path: &Path, + processed: &mut Vec, +) -> Result { + // Checks for cyclic dependencies + let str_path = toml_path.to_str().expect("ICE - path is empty"); + if processed.contains(&str_path.to_string()) { + let mut cycle = false; + let mut message = String::new(); + for toml in processed { + cycle = cycle || toml == str_path; + if cycle { + message += &format!("{} referencing ", toml); + } + } + message += str_path; + return Err(ManifestError::CyclicDependency { cycle: message }); + } + // Adds the package to the set of resolved packages + if let Some(str) = toml_path.to_str() { + processed.push(str.to_string()); + } + + let nargo_toml = read_toml(toml_path)?; + + let result = match nargo_toml.config { + Config::Package { package_config } => { + package_config.resolve_to_package(&nargo_toml.root_dir, processed) + } + Config::Workspace { .. } => { + Err(ManifestError::UnexpectedWorkspace(toml_path.to_path_buf())) + } + }; + let pos = + processed.iter().position(|toml| toml == str_path).expect("added package must be here"); + processed.remove(pos); + result +} + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum PackageSelection { + Selected(CrateName), + DefaultOrAll, + All, +} + +/// Resolves a Nargo.toml file into a `Workspace` struct as defined by our `nargo` core. +pub fn resolve_workspace_from_toml( + toml_path: &Path, + package_selection: PackageSelection, + current_compiler_version: Option, +) -> Result { + let nargo_toml = read_toml(toml_path)?; + let workspace = toml_to_workspace(nargo_toml, package_selection)?; + if let Some(current_compiler_version) = current_compiler_version { + semver::semver_check_workspace(&workspace, current_compiler_version)?; + } + Ok(workspace) +} + +#[cfg(test)] +mod tests { + use std::{ + path::{Path, PathBuf}, + str::FromStr, + }; + + use test_case::test_matrix; + + use crate::{find_root, Config, ManifestError}; + + #[test] + fn parse_standard_toml() { + let src = r#" + + [package] + name = "test" + authors = ["kev", "foo"] + compiler_version = "*" + + [dependencies] + rand = { tag = "next", git = "https://github.com/rust-lang-nursery/rand"} + cool = { tag = "next", git = "https://github.com/rust-lang-nursery/rand"} + hello = {path = "./noir_driver"} + "#; + + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } + + #[test] + fn parse_package_toml_no_deps() { + let src = r#" + [package] + name = "test" + authors = ["kev", "foo"] + compiler_version = "*" + "#; + + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } + + #[test] + fn parse_workspace_toml() { + let src = r#" + [workspace] + members = ["a", "b"] + "#; + + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } + + #[test] + fn parse_workspace_default_member_toml() { + let src = r#" + [workspace] + members = ["a", "b"] + default-member = "a" + "#; + + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } + + #[test] + fn parse_package_expression_width_toml() { + let src = r#" + [package] + name = "test" + version = "0.1.0" + type = "bin" + authors = [""] + expression_width = "3" + "#; + + assert!(Config::try_from(String::from(src)).is_ok()); + assert!(Config::try_from(src).is_ok()); + } + + /// Test that `find_root` handles all kinds of prefixes. + /// (It dispatches based on `workspace` to methods which handle paths differently). + #[test_matrix( + [true, false], + ["C:\\foo\\bar", "//shared/foo/bar", "/foo/bar", "bar/baz", ""] + )] + fn test_find_root_does_not_panic(workspace: bool, path: &str) { + let path = PathBuf::from_str(path).unwrap(); + let error = find_root(&path, workspace).expect_err("non-existing paths"); + assert!(matches!(error, ManifestError::MissingFile(_))); + } + + /// Test to demonstrate how `find_root` works. + #[test] + fn test_find_root_example() { + const INDENT_SIZE: usize = 4; + /// Create directories and files according to a YAML-like layout below + fn setup(layout: &str, root: &Path) { + fn is_dir(item: &str) -> bool { + !item.contains('.') + } + let mut current_dir = root.to_path_buf(); + let mut current_indent = 0; + let mut last_item: Option = None; + + for line in layout.lines() { + if let Some((prefix, item)) = line.split_once('-') { + let item = item.replace(std::path::MAIN_SEPARATOR, "_").trim().to_string(); + + let indent = prefix.len() / INDENT_SIZE; + + if last_item.is_none() { + current_indent = indent; + } + + assert!( + indent <= current_indent + 1, + "cannot increase indent by more than {INDENT_SIZE}; item = {item}, current_dir={}", current_dir.display() + ); + + // Go into the last created directory + if indent > current_indent && last_item.is_some() { + let last_item = last_item.unwrap(); + assert!(is_dir(&last_item), "last item was not a dir: {last_item}"); + current_dir.push(last_item); + current_indent += 1; + } + // Go back into an ancestor directory + while indent < current_indent { + current_dir.pop(); + current_indent -= 1; + } + // Create a file or a directory + let item_path = current_dir.join(&item); + if is_dir(&item) { + std::fs::create_dir(&item_path).unwrap_or_else(|e| { + panic!("failed to create dir {}: {e}", item_path.display()) + }); + } else { + std::fs::write(&item_path, "").expect("failed to create file"); + } + + last_item = Some(item); + } + } + } + + // Temporary directory to hold the project. + let tmp = tempfile::tempdir().unwrap(); + // Join a string path to the tmp dir + let path = |p: &str| tmp.path().join(p); + // Check that an expected root is found + let assert_ok = |current_dir: &str, ws: bool, exp: &str| { + let root = find_root(&path(current_dir), ws).expect("should find a root"); + assert_eq!(root, path(exp)); + }; + // Check that a root is not found + let assert_err = |current_dir: &str| { + find_root(&path(current_dir), true).expect_err("shouldn't find a root"); + }; + + let layout = r" + - project + - docs + - workspace + - packages + - foo + - Nargo.toml + - Prover.toml + - src + - main.nr + - bar + - Nargo.toml + - src + - lib.nr + - Nargo.toml + - examples + - baz + - Nargo.toml + - src + - main.nr + "; + + // Set up the file system. + setup(layout, tmp.path()); + + assert_err("dummy"); + assert_err("project/docs"); + assert_err("project/examples"); + assert_ok("project/workspace", true, "project/workspace"); + assert_ok("project/workspace", false, "project/workspace"); + assert_ok("project/workspace/packages/foo", true, "project/workspace"); + assert_ok("project/workspace/packages/bar", false, "project/workspace/packages/bar"); + assert_ok("project/examples/baz/src", true, "project/examples/baz"); + assert_ok("project/examples/baz/src", false, "project/examples/baz"); + } +} diff --git a/tooling/nargo_toml/src/semver.rs b/tooling/nargo_toml/src/semver.rs new file mode 100644 index 00000000000..ececa1b30dd --- /dev/null +++ b/tooling/nargo_toml/src/semver.rs @@ -0,0 +1,250 @@ +use crate::{errors::SemverError, ManifestError}; +use nargo::{ + package::{Dependency, Package}, + workspace::Workspace, +}; +use noirc_driver::CrateName; +use semver::{Error, Prerelease, Version, VersionReq}; + +// Parse a semver compatible version string +pub(crate) fn parse_semver_compatible_version(version: &str) -> Result { + let mut version = Version::parse(version)?; + version.pre = Prerelease::EMPTY; + Ok(version) +} + +// Check that all of the packages in the workspace are compatible with the current compiler version +pub(crate) fn semver_check_workspace( + workspace: &Workspace, + current_compiler_version: String, +) -> Result<(), ManifestError> { + let version = parse_semver_compatible_version(¤t_compiler_version) + .expect("The compiler version is not a valid semver version"); + for package in &workspace.members { + semver_check_package(package, &version).map_err(ManifestError::SemverError)?; + } + + Ok(()) +} + +// Check that a package and all of its dependencies are compatible with the current compiler version +fn semver_check_package(package: &Package, compiler_version: &Version) -> Result<(), SemverError> { + // Check that this package's compiler version requirements are satisfied + if let Some(version) = &package.compiler_required_version { + let version_req = match VersionReq::parse(version) { + Ok(version_req) => version_req, + Err(err) => { + return Err(SemverError::CouldNotParseRequiredVersion { + package_name: package.name.clone().into(), + error: err.to_string(), + }) + } + }; + + validate_compiler_version_requirement(&package.name, &version_req)?; + + if !version_req.matches(compiler_version) { + return Err(SemverError::IncompatibleVersion { + package_name: package.name.clone(), + required_compiler_version: version.clone(), + compiler_version_found: strip_build_meta_data(compiler_version), + }); + }; + } + + // Check that all of this package's dependencies' compiler version requirements are satisfied + for dep in package.dependencies.values() { + match dep { + Dependency::Local { package } | Dependency::Remote { package } => { + semver_check_package(package, compiler_version)?; + } + } + } + + Ok(()) +} + +fn validate_compiler_version_requirement( + package_name: &CrateName, + required_compiler_version: &VersionReq, +) -> Result<(), SemverError> { + if required_compiler_version.comparators.iter().any(|comparator| !comparator.pre.is_empty()) { + return Err(SemverError::InvalidCompilerVersionRequirement { + package_name: package_name.clone(), + required_compiler_version: required_compiler_version.to_string(), + }); + } + + Ok(()) +} + +// Strip the build meta data from the version string since it is ignored by semver. +fn strip_build_meta_data(version: &Version) -> String { + let version_string = version.to_string(); + let mut split = version_string.split('+'); + split.next().expect("split was called on an empty string").to_string() +} + +#[cfg(test)] +mod tests { + use std::{collections::BTreeMap, path::PathBuf, str::FromStr}; + + use nargo::package::PackageType; + use noirc_frontend::graph::CrateName; + + use super::*; + + #[test] + fn test_semver_check_smoke() { + let compiler_version = Version::parse("0.1.0").unwrap(); + + let mut package = Package { + compiler_required_version: Some("0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("test").unwrap(), + dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), + expression_width: None, + }; + if let Err(err) = semver_check_package(&package, &compiler_version) { + panic!("semver check should have passed. compiler version is 0.1.0 and required version from the package is 0.1.0\n error: {err:?}") + }; + + package.compiler_required_version = Some("0.2.0".to_string()); + let got_err = match semver_check_package(&package, &compiler_version) { + Ok(_) => panic!("semver check should have failed. compiler version is 0.1.0 and required version from the package is 0.2.0"), + Err(err) => err, + }; + + let expected_version_error = SemverError::IncompatibleVersion { + package_name: CrateName::from_str("test").unwrap(), + required_compiler_version: "0.2.0".to_string(), + compiler_version_found: "0.1.0".to_string(), + }; + assert_eq!(got_err, expected_version_error); + } + + #[test] + fn test_semver_dependency_check_smoke() { + let compiler_version = Version::parse("0.1.0").unwrap(); + + let mut package = Package { + compiler_required_version: Some("0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("test").unwrap(), + dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), + expression_width: None, + }; + + let valid_dependency = Package { + compiler_required_version: Some("0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("good_dependency").unwrap(), + dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), + expression_width: None, + }; + let invalid_dependency = Package { + compiler_required_version: Some("0.2.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("bad_dependency").unwrap(), + dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), + expression_width: None, + }; + + package.dependencies.insert( + CrateName::from_str("test_dep_valid").unwrap(), + Dependency::Local { package: valid_dependency.clone() }, + ); + + if let Err(err) = semver_check_package(&package, &compiler_version) { + panic!("semver check should have passed. compiler version is 0.1.0 and required version from the package is 0.1.0\n error: {err:?}") + }; + + package.dependencies.insert( + CrateName::from_str("test_dep_invalid").unwrap(), + Dependency::Local { package: invalid_dependency.clone() }, + ); + let got_err = match semver_check_package(&package,&compiler_version) { + Ok(_) => panic!("semver check should have failed. compiler version is 0.1.0 and required version from the package is 0.2.0"), + Err(err) => err, + }; + + let expected_version_error = SemverError::IncompatibleVersion { + package_name: CrateName::from_str("bad_dependency").unwrap(), + required_compiler_version: "0.2.0".to_string(), + compiler_version_found: "0.1.0".to_string(), + }; + assert_eq!(got_err, expected_version_error); + } + + #[test] + fn test_semver_carrot() { + let compiler_version = Version::parse("0.2.0").unwrap(); + + let package = Package { + compiler_required_version: Some(">=0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("test").unwrap(), + dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), + expression_width: None, + }; + + if let Err(err) = semver_check_package(&package, &compiler_version) { + panic!("semver check should have passed. compiler version is 0.2.0 and required version from the package is >=0.1.0\n error: {err:?}") + }; + } + + #[test] + fn test_semver_prerelease() { + let compiler_version = parse_semver_compatible_version("1.0.0-beta.0").unwrap(); + + let package = Package { + compiler_required_version: Some(">=0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("test").unwrap(), + dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), + expression_width: None, + }; + + if let Err(err) = semver_check_package(&package, &compiler_version) { + panic!("{err}"); + }; + } + + #[test] + fn test_semver_build_data() { + let compiler_version = Version::parse("0.1.0+this-is-ignored-by-semver").unwrap(); + + let package = Package { + compiler_required_version: Some("0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("test").unwrap(), + dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), + expression_width: None, + }; + + if let Err(err) = semver_check_package(&package, &compiler_version) { + panic!("semver check should have passed. compiler version is 0.1.0+build_data and required version from the package is 0.1.0\n The build data should be ignored\n error: {err:?}") + }; + } +} diff --git a/tooling/noir_codegen/.eslintignore b/tooling/noir_codegen/.eslintignore new file mode 100644 index 00000000000..491fc35975b --- /dev/null +++ b/tooling/noir_codegen/.eslintignore @@ -0,0 +1,2 @@ +node_modules +lib diff --git a/tooling/noir_codegen/.eslintrc.cjs b/tooling/noir_codegen/.eslintrc.cjs new file mode 100644 index 00000000000..33335c2a877 --- /dev/null +++ b/tooling/noir_codegen/.eslintrc.cjs @@ -0,0 +1,3 @@ +module.exports = { + extends: ["../../.eslintrc.js"], +}; diff --git a/tooling/noir_codegen/.gitignore b/tooling/noir_codegen/.gitignore new file mode 100644 index 00000000000..29b0e40ffa8 --- /dev/null +++ b/tooling/noir_codegen/.gitignore @@ -0,0 +1,5 @@ +crs +lib + +test/codegen +test/test_lib/export diff --git a/tooling/noir_codegen/.mocharc.json b/tooling/noir_codegen/.mocharc.json new file mode 100644 index 00000000000..82855d2ddf4 --- /dev/null +++ b/tooling/noir_codegen/.mocharc.json @@ -0,0 +1,11 @@ +{ + "require": "ts-node/register", + "loader": "ts-node/esm", + "extensions": [ + "ts", + "cjs" + ], + "spec": [ + "test/**/*.test.ts*" + ] +} \ No newline at end of file diff --git a/tooling/noir_codegen/README.md b/tooling/noir_codegen/README.md new file mode 100644 index 00000000000..c24c12ff987 --- /dev/null +++ b/tooling/noir_codegen/README.md @@ -0,0 +1,4 @@ + +## Acknowledgements + +`noir-codegen` repurposes the CLI code from https://github.com/dethcrypto/TypeChain, used under the MIT license. \ No newline at end of file diff --git a/tooling/noir_codegen/package.json b/tooling/noir_codegen/package.json new file mode 100644 index 00000000000..351a29ae595 --- /dev/null +++ b/tooling/noir_codegen/package.json @@ -0,0 +1,63 @@ +{ + "name": "@noir-lang/noir_codegen", + "contributors": [ + "The Noir Team " + ], + "version": "1.0.0-beta.1", + "packageManager": "yarn@3.5.1", + "license": "(MIT OR Apache-2.0)", + "type": "module", + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "compiler/wasm", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, + "dependencies": { + "@noir-lang/types": "workspace:*", + "glob": "^10.3.10", + "ts-command-line-args": "^2.5.1" + }, + "files": [ + "lib", + "package.json" + ], + "source": "src/index.ts", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "bin": { + "noir-codegen": "lib/main.js" + }, + "scripts": { + "dev": "tsc-multi --watch", + "build": "tsc", + "test": "yarn test:codegen && yarn test:node && yarn test:clean", + "test:codegen": "nargo export --program-dir=./test/test_lib && tsx src/main.ts ./test/test_lib/export/** --out-dir ./test/codegen", + "test:node": "mocha --timeout 25000 --exit --config ./.mocharc.json", + "test:clean": "rm -rf ./test/codegen ./test/test_lib/export", + "prettier": "prettier 'src/**/*.ts'", + "prettier:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", + "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0", + "nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", + "publish": "echo 📡 publishing `$npm_package_name` && yarn npm publish", + "clean": "rm -rf ./lib" + }, + "devDependencies": { + "@noir-lang/noir_js": "workspace:*", + "@types/chai": "^4", + "@types/mocha": "^10.0.1", + "@types/node": "^20.6.2", + "@types/prettier": "^3", + "chai": "^4.4.1", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", + "mocha": "^10.2.0", + "prettier": "3.2.5", + "ts-node": "^10.9.1", + "tsx": "^4.6.2", + "typescript": "^5.4.2" + } +} diff --git a/tooling/noir_codegen/src/index.ts b/tooling/noir_codegen/src/index.ts new file mode 100644 index 00000000000..d00990f01bc --- /dev/null +++ b/tooling/noir_codegen/src/index.ts @@ -0,0 +1,17 @@ +import { CompiledCircuit } from '@noir-lang/types'; +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(); +}; diff --git a/tooling/noir_codegen/src/main.ts b/tooling/noir_codegen/src/main.ts new file mode 100644 index 00000000000..835b24a9e48 --- /dev/null +++ b/tooling/noir_codegen/src/main.ts @@ -0,0 +1,47 @@ +#! /usr/bin/env node + +import { CompiledCircuit } from '@noir-lang/types'; +import fs from 'fs'; +import path from 'path'; +import { parseArgs } from './parseArgs.js'; +import { glob } from './utils/glob.js'; +import { codegen } from './index.js'; + +function main() { + const cliConfig = parseArgs(); + const cwd = process.cwd(); + + const files = getFilesToProcess(cwd, cliConfig.files); + if (files.length === 0) { + throw new Error('No files passed.' + '\n' + `\`${cliConfig.files}\` didn't match any input files in ${cwd}`); + } + + const programs = files.map((file_path): [string, CompiledCircuit] => { + const program_name = path.parse(file_path).name; + const file_contents = fs.readFileSync(file_path).toString(); + const { abi, bytecode } = JSON.parse(file_contents); + + return [program_name, { abi, bytecode }]; + }); + + const result = codegen(programs, !cliConfig.externalArtifact, cliConfig.useFixedLengthArrays); + + const outputDir = path.resolve(cliConfig.outDir ?? './codegen'); + const outputFile = path.join(outputDir, 'index.ts'); + if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir); + fs.writeFileSync(outputFile, result); +} + +function getFilesToProcess(cwd: string, filesOrPattern: string[]) { + let res = glob(cwd, filesOrPattern); + + if (res.length === 0) { + // If there are no files found, but first parameter is surrounded with single quotes, we try again without quotes + const match = filesOrPattern[0].match(/'([\s\S]*)'/)?.[1]; + if (match) res = glob(cwd, [match]); + } + + return res; +} + +main(); diff --git a/tooling/noir_codegen/src/parseArgs.ts b/tooling/noir_codegen/src/parseArgs.ts new file mode 100644 index 00000000000..83b6c8bcdb2 --- /dev/null +++ b/tooling/noir_codegen/src/parseArgs.ts @@ -0,0 +1,81 @@ +import { parse as commandLineArgs } from 'ts-command-line-args'; + +const DEFAULT_GLOB_PATTERN = './target/**/*.json'; + +export interface ParsedArgs { + files: string[]; + outDir?: string | undefined; + inputDir?: string | undefined; + externalArtifact: boolean; + useFixedLengthArrays: boolean; +} + +export function parseArgs(): ParsedArgs { + const rawOptions = commandLineArgs( + { + glob: { + type: String, + defaultOption: true, + multiple: true, + defaultValue: [DEFAULT_GLOB_PATTERN], + description: + 'Pattern that will be used to find program artifacts. Remember about adding quotes: noir-codegen "**/*.json".', + }, + 'out-dir': { type: String, optional: true, description: 'Output directory for generated files.' }, + 'input-dir': { + type: String, + optional: true, + description: + 'Directory containing program artifact files. Inferred as lowest common path of all files if not specified.', + }, + help: { type: Boolean, defaultValue: false, alias: 'h', description: 'Prints this message.' }, + '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', + headerContentSections: [ + { + content: `\ + noir-codegen generates TypeScript wrappers for Noir programs to simplify replicating your Noir logic in JS.`, + }, + ], + footerContentSections: [ + { + header: 'Example Usage', + content: `\ + noir-codegen --out-dir app/noir_programs './target/*.json' + + + You can read more about noir-codegen at {underline https://github.com/noir-lang/noir}.`, + }, + ], + }, + ); + + return { + files: rawOptions.glob, + outDir: rawOptions['out-dir'], + inputDir: rawOptions['input-dir'], + externalArtifact: rawOptions['external-artifact'], + useFixedLengthArrays: rawOptions['fixed-length-arrays'], + }; +} + +interface CommandLineArgs { + glob: string[]; + '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/glob.ts b/tooling/noir_codegen/src/utils/glob.ts new file mode 100644 index 00000000000..a1e4c3b1ea1 --- /dev/null +++ b/tooling/noir_codegen/src/utils/glob.ts @@ -0,0 +1,6 @@ +import { sync as globSync } from 'glob'; + +export function glob(cwd: string, patternsOrFiles: string[]): string[] { + const matches = patternsOrFiles.map((p) => globSync(p, { ignore: 'node_modules/**', absolute: true, cwd })); + return [...new Set(matches.flat())]; +} 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 new file mode 100644 index 00000000000..afc7769ed9e --- /dev/null +++ b/tooling/noir_codegen/test/index.test.ts @@ -0,0 +1,106 @@ +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, u32, ForeignCallHandler } from './codegen/index.js'; + +it('codegens a callable function', async () => { + const my_struct = { foo: true, bar: ['123', '123', '123', '123'], baz: '0x00' }; + + const [sum, constant, struct]: [u64, u32, MyStruct] = await exported_function_foo( + '2', + '3', + ['0x00', '0x00', '0x00', '0x00', '0x00'], + { + foo: my_struct, + bar: [my_struct, my_struct], + baz: '64', + }, + '12345', + ); + + expect(sum).to.be.eq('0x05'); + expect(constant).to.be.eq('0x03'); + expect(struct).to.be.deep.eq(my_struct); +}); + +it('allows passing a custom foreign call handler', async () => { + let observedName = ''; + let observedInputs: string[][] = []; + const foreignCallHandler: ForeignCallHandler = async (name: string, inputs: string[][]) => { + // Throwing inside the oracle callback causes a timeout so we log the observed values + // and defer the check against expected values until after the execution is complete. + observedName = name; + observedInputs = inputs; + + return []; + }; + + const my_struct = { foo: true, bar: ['123', '123', '123', '123'], baz: '0x00' }; + + const [sum, constant, struct]: [u64, u32, MyStruct] = await exported_function_foo( + '2', + '3', + ['0x00', '0x00', '0x00', '0x00', '0x00'], + { + foo: my_struct, + bar: [my_struct, my_struct], + baz: '64', + }, + '12345', + foreignCallHandler, + ); + + expect(observedName).to.be.eq('print'); + expect(observedInputs).to.be.deep.eq([ + // add newline? + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + // x + ['0x0000000000000000000000000000000000000000000000000000000000000002'], + // Type metadata + [ + '0x000000000000000000000000000000000000000000000000000000000000007b', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x000000000000000000000000000000000000000000000000000000000000006b', + '0x0000000000000000000000000000000000000000000000000000000000000069', + '0x000000000000000000000000000000000000000000000000000000000000006e', + '0x0000000000000000000000000000000000000000000000000000000000000064', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x000000000000000000000000000000000000000000000000000000000000003a', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x0000000000000000000000000000000000000000000000000000000000000075', + '0x000000000000000000000000000000000000000000000000000000000000006e', + '0x0000000000000000000000000000000000000000000000000000000000000073', + '0x0000000000000000000000000000000000000000000000000000000000000069', + '0x0000000000000000000000000000000000000000000000000000000000000067', + '0x000000000000000000000000000000000000000000000000000000000000006e', + '0x0000000000000000000000000000000000000000000000000000000000000065', + '0x0000000000000000000000000000000000000000000000000000000000000064', + '0x0000000000000000000000000000000000000000000000000000000000000069', + '0x000000000000000000000000000000000000000000000000000000000000006e', + '0x0000000000000000000000000000000000000000000000000000000000000074', + '0x0000000000000000000000000000000000000000000000000000000000000065', + '0x0000000000000000000000000000000000000000000000000000000000000067', + '0x0000000000000000000000000000000000000000000000000000000000000065', + '0x0000000000000000000000000000000000000000000000000000000000000072', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x000000000000000000000000000000000000000000000000000000000000002c', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x0000000000000000000000000000000000000000000000000000000000000077', + '0x0000000000000000000000000000000000000000000000000000000000000069', + '0x0000000000000000000000000000000000000000000000000000000000000064', + '0x0000000000000000000000000000000000000000000000000000000000000074', + '0x0000000000000000000000000000000000000000000000000000000000000068', + '0x0000000000000000000000000000000000000000000000000000000000000022', + '0x000000000000000000000000000000000000000000000000000000000000003a', + '0x0000000000000000000000000000000000000000000000000000000000000036', + '0x0000000000000000000000000000000000000000000000000000000000000034', + '0x000000000000000000000000000000000000000000000000000000000000007d', + ], + // format string? + ['0x0000000000000000000000000000000000000000000000000000000000000000'], + ]); + + expect(sum).to.be.eq('0x05'); + expect(constant).to.be.eq('0x03'); + expect(struct).to.be.deep.eq(my_struct); +}); diff --git a/tooling/noir_codegen/test/test_lib/Nargo.toml b/tooling/noir_codegen/test/test_lib/Nargo.toml new file mode 100644 index 00000000000..74b6167b614 --- /dev/null +++ b/tooling/noir_codegen/test/test_lib/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "test_lib" +type = "lib" +authors = [""] +[dependencies] diff --git a/tooling/noir_codegen/test/test_lib/src/lib.nr b/tooling/noir_codegen/test/test_lib/src/lib.nr new file mode 100644 index 00000000000..4229de06157 --- /dev/null +++ b/tooling/noir_codegen/test/test_lib/src/lib.nr @@ -0,0 +1,33 @@ +struct MyStruct { + foo: bool, + bar: [str; BAR_SIZE], + baz: Field +} + +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<2,3,4, Field>, + string: str<5> +) -> (u64, u32, MyStruct<3, 4>) { + assert(array.len() == 5); + assert(my_struct.foo.foo); + assert(string == "12345"); + + print(x); + assert(x < y); + (x + y, 3, my_struct.foo) +} + +#[export] +fn exported_function_bar(my_struct: NestedStruct<1,2,3, u64>) -> (u64) { + my_struct.baz +} diff --git a/tooling/noir_codegen/tsconfig.json b/tooling/noir_codegen/tsconfig.json new file mode 100644 index 00000000000..30dd2a7ee5f --- /dev/null +++ b/tooling/noir_codegen/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "esnext", + "declaration": true, + "emitDeclarationOnly": false, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "outDir": "./lib", + "esModuleInterop": true, + "resolveJsonModule": true, + "strict": true, + "noImplicitAny": false, + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/tooling/noir_js/.eslintignore b/tooling/noir_js/.eslintignore new file mode 100644 index 00000000000..e34f38f3450 --- /dev/null +++ b/tooling/noir_js/.eslintignore @@ -0,0 +1,3 @@ +node_modules +test/backend/barretenberg.ts +lib diff --git a/tooling/noir_js/.eslintrc.cjs b/tooling/noir_js/.eslintrc.cjs new file mode 100644 index 00000000000..33335c2a877 --- /dev/null +++ b/tooling/noir_js/.eslintrc.cjs @@ -0,0 +1,3 @@ +module.exports = { + extends: ["../../.eslintrc.js"], +}; diff --git a/tooling/noir_js/.gitignore b/tooling/noir_js/.gitignore new file mode 100644 index 00000000000..a55d1794141 --- /dev/null +++ b/tooling/noir_js/.gitignore @@ -0,0 +1 @@ +crs diff --git a/tooling/noir_js/.mocharc.cjs.json b/tooling/noir_js/.mocharc.cjs.json new file mode 100644 index 00000000000..c1c37373f18 --- /dev/null +++ b/tooling/noir_js/.mocharc.cjs.json @@ -0,0 +1,6 @@ +{ + "extensions": ["cjs"], + "spec": [ + "test/node/**/*.test.cjs" + ] +} \ No newline at end of file diff --git a/tooling/noir_js/.mocharc.json b/tooling/noir_js/.mocharc.json new file mode 100644 index 00000000000..be7e952e7ca --- /dev/null +++ b/tooling/noir_js/.mocharc.json @@ -0,0 +1,7 @@ +{ + "require": "tsx", + "extensions": ["ts", "cjs"], + "spec": [ + "test/node/**/*.test.ts*" + ] +} \ No newline at end of file diff --git a/tooling/noir_js/package.json b/tooling/noir_js/package.json new file mode 100644 index 00000000000..2a6dc614cb0 --- /dev/null +++ b/tooling/noir_js/package.json @@ -0,0 +1,66 @@ +{ + "name": "@noir-lang/noir_js", + "contributors": [ + "The Noir Team " + ], + "version": "1.0.0-beta.1", + "packageManager": "yarn@3.5.1", + "license": "(MIT OR Apache-2.0)", + "type": "module", + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "tooling/noir_js", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, + "dependencies": { + "@noir-lang/acvm_js": "workspace:*", + "@noir-lang/noirc_abi": "workspace:*", + "@noir-lang/types": "workspace:*" + }, + "files": [ + "lib", + "package.json" + ], + "source": "src/index.ts", + "main": "lib/index.cjs", + "module": "lib/index.mjs", + "exports": { + "require": "./lib/index.cjs", + "types": "./lib/index.d.ts", + "default": "./lib/index.mjs" + }, + "types": "lib/index.d.ts", + "scripts": { + "dev": "tsc-multi --watch", + "build": "tsc-multi", + "test": "yarn test:compile_program && yarn test:node:esm && yarn test:node:cjs", + "test:compile_program": "./scripts/compile_test_programs.sh", + "test:node:esm": "mocha --timeout 25000 --exit --config ./.mocharc.json", + "test:node:cjs": "mocha --timeout 25000 --exit --config ./.mocharc.cjs.json", + "prettier": "prettier 'src/**/*.ts'", + "prettier:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", + "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0", + "nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", + "publish": "echo 📡 publishing `$npm_package_name` && yarn npm publish", + "clean": "rm -rf ./lib" + }, + "devDependencies": { + "@types/chai": "^4", + "@types/mocha": "^10.0.1", + "@types/node": "^20.6.2", + "@types/prettier": "^3", + "chai": "^4.4.1", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", + "mocha": "^10.2.0", + "prettier": "3.2.5", + "ts-node": "^10.9.1", + "tsc-multi": "^1.1.0", + "tsx": "^4.6.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 new file mode 100755 index 00000000000..c65aea823a4 --- /dev/null +++ b/tooling/noir_js/scripts/compile_test_programs.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +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 +nargo --program-dir ./test/noir_compiled_examples/databus compile --force diff --git a/tooling/noir_js/src/base64_decode.ts b/tooling/noir_js/src/base64_decode.ts new file mode 100644 index 00000000000..d53aed187c7 --- /dev/null +++ b/tooling/noir_js/src/base64_decode.ts @@ -0,0 +1,13 @@ +// Since this is a simple function, we can use feature detection to +// see if we are in the nodeJs environment or the browser environment. +export function base64Decode(input: string): Uint8Array { + if (typeof Buffer !== 'undefined') { + // Node.js environment + return Buffer.from(input, 'base64'); + } else if (typeof atob === 'function') { + // Browser environment + return Uint8Array.from(atob(input), (c) => c.charCodeAt(0)); + } else { + throw new Error('No implementation found for base64 decoding.'); + } +} diff --git a/tooling/noir_js/src/index.ts b/tooling/noir_js/src/index.ts new file mode 100644 index 00000000000..ed0999a960c --- /dev/null +++ b/tooling/noir_js/src/index.ts @@ -0,0 +1,17 @@ +import * as acvm from '@noir-lang/acvm_js'; +import * as abi from '@noir-lang/noirc_abi'; +import { CompiledCircuit } from '@noir-lang/types'; + +export { ecdsa_secp256r1_verify, ecdsa_secp256k1_verify, blake2s256, xor, and } from '@noir-lang/acvm_js'; + +export { InputMap } from '@noir-lang/noirc_abi'; +export { WitnessMap, ForeignCallHandler, ForeignCallInput, ForeignCallOutput } from '@noir-lang/acvm_js'; + +export { Noir } from './program.js'; +export { ErrorWithPayload } from './witness_generation.js'; + +/** @ignore */ +export { acvm, abi }; + +// type exports for typedoc +export { CompiledCircuit }; diff --git a/tooling/noir_js/src/program.ts b/tooling/noir_js/src/program.ts new file mode 100644 index 00000000000..accd89dc385 --- /dev/null +++ b/tooling/noir_js/src/program.ts @@ -0,0 +1,38 @@ +import { CompiledCircuit } from '@noir-lang/types'; +import { generateWitness } from './witness_generation.js'; +import initAbi, { abiDecode, InputMap, InputValue } from '@noir-lang/noirc_abi'; +import initACVM, { compressWitnessStack, ForeignCallHandler } from '@noir-lang/acvm_js'; + +export class Noir { + constructor(private circuit: CompiledCircuit) {} + + /** @ignore */ + async init(): Promise { + // If these are available, then we are in the + // web environment. For the node environment, this + // is a no-op. + if (typeof initAbi === 'function') { + await Promise.all([initAbi(), initACVM()]); + } + } + + /** + * @description + * Allows to execute a circuit to get its witness and return value. + * + * @example + * ```typescript + * async execute(inputs) + * ``` + */ + async execute( + inputs: InputMap, + foreignCallHandler?: ForeignCallHandler, + ): Promise<{ witness: Uint8Array; returnValue: InputValue }> { + await this.init(); + const witness_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 new file mode 100644 index 00000000000..c84cb2e83b3 --- /dev/null +++ b/tooling/noir_js/src/witness_generation.ts @@ -0,0 +1,65 @@ +import { abiDecodeError, abiEncode, InputMap } from '@noir-lang/noirc_abi'; +import { base64Decode } from './base64_decode.js'; +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') { + // By default we do not print anything for `print` foreign calls due to a need for formatting, + // however we provide an empty response in order to not halt execution. + // + // If a user needs to print values then they should provide a custom foreign call handler. + return []; + } + throw Error(`Unexpected oracle during execution: ${name}(${args.join(', ')})`); +}; + +// 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 { + // 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 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/cjs.test.cjs b/tooling/noir_js/test/node/cjs.test.cjs new file mode 100644 index 00000000000..8698f9dfe2b --- /dev/null +++ b/tooling/noir_js/test/node/cjs.test.cjs @@ -0,0 +1,80 @@ +/* eslint-disable no-undef */ +/* eslint-disable @typescript-eslint/no-var-requires */ +const chai = require('chai'); +const assert_lt_json = require('../noir_compiled_examples/assert_lt/target/assert_lt.json'); +const { Noir } = require('@noir-lang/noir_js'); + +it('generates witnesses successfully', async () => { + const inputs = { + x: '2', + y: '3', + }; + const _solvedWitness = await new Noir(assert_lt_json).execute(inputs); +}); + +it('string input and number input are the same', async () => { + const inputsString = { + x: '2', + y: '3', + }; + const inputsNumber = { + x: 2, + y: 3, + }; + const solvedWitnessString = await new Noir(assert_lt_json).execute(inputsString); + const solvedWitnessNumber = await new Noir(assert_lt_json).execute(inputsNumber); + chai.expect(solvedWitnessString).to.deep.equal(solvedWitnessNumber); +}); + +it('string input and number input are the same', async () => { + const inputsString = { + x: '2', + y: '3', + }; + const inputsNumber = { + x: 2, + y: 3, + }; + + const solvedWitnessString = await new Noir(assert_lt_json).execute(inputsString); + const solvedWitnessNumber = await new Noir(assert_lt_json).execute(inputsNumber); + chai.expect(solvedWitnessString).to.deep.equal(solvedWitnessNumber); +}); + +it('0x prefixed string input for inputs will throw', async () => { + const inputsHexPrefix = { + x: '0x2', + y: '0x3', + }; + + try { + await new Noir(assert_lt_json).execute(inputsHexPrefix); + chai.expect.fail( + 'Expected generatedWitness to throw, due to inputs being prefixed with 0x. Currently not supported', + ); + } catch (error) { + // Successfully errored due to 0x not being supported. Update this test once/if we choose + // to support 0x prefixed inputs. + } +}); + +describe('input validation', () => { + it('x should be a uint64 not a string', async () => { + const inputs = { + x: 'foo', + y: '3', + }; + + try { + await new Noir(assert_lt_json).execute(inputs); + chai.expect.fail('Expected generatedWitness to throw, due to x not being convertible to a uint64'); + } catch (error) { + const knownError = error; + chai + .expect(knownError.message) + .to.equal( + 'Expected witness values to be integers, provided value causes `invalid digit found in string` error', + ); + } + }); +}); diff --git a/tooling/noir_js/test/node/execute.test.ts b/tooling/noir_js/test/node/execute.test.ts new file mode 100644 index 00000000000..ceac21b2860 --- /dev/null +++ b/tooling/noir_js/test/node/execute.test.ts @@ -0,0 +1,72 @@ +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 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 databus_json from '../noir_compiled_examples/databus/target/databus.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; +const databus_program = databus_json as CompiledCircuit; + +it('executes a single-ACIR program correctly', async () => { + const inputs = { + x: '2', + y: '3', + }; + const { returnValue } = await new Noir(assert_lt_program).execute(inputs); + + expect(returnValue).to.be.eq('0x05'); +}); + +it('successfully executes a program with multiple acir circuits', async () => { + const inputs = { + x: '10', + }; + expect(() => new Noir(fold_fibonacci_program).execute(inputs)).to.not.throw(); +}); + +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 decodes the return values from a program using the databus', async () => { + const inputs = { + x: '3', + y: '4', + z: [1, 2, 3, 4], + }; + const { returnValue } = await new Noir(databus_program).execute(inputs); + expect(returnValue).to.be.eq('0x09'); +}); diff --git a/tooling/noir_js/test/node/smoke.test.ts b/tooling/noir_js/test/node/smoke.test.ts new file mode 100644 index 00000000000..6993a44f66e --- /dev/null +++ b/tooling/noir_js/test/node/smoke.test.ts @@ -0,0 +1,77 @@ +import { expect } from 'chai'; +import assert_lt_json from '../noir_compiled_examples/assert_lt/target/assert_lt.json' assert { type: 'json' }; +import { CompiledCircuit } from '@noir-lang/types'; +import { Noir } from '@noir-lang/noir_js'; + +const assert_lt_program = assert_lt_json as CompiledCircuit; + +it('generates witnesses successfully', async () => { + const inputs = { + x: '2', + y: '3', + }; + expect(() => new Noir(assert_lt_program).execute(inputs)).to.not.throw; +}); + +it('string input and number input are the same', async () => { + const inputsString = { + x: '2', + y: '3', + }; + const inputsNumber = { + x: 2, + y: 3, + }; + const solvedWitnessString = await new Noir(assert_lt_program).execute(inputsString); + const solvedWitnessNumber = await new Noir(assert_lt_program).execute(inputsNumber); + expect(solvedWitnessString).to.deep.equal(solvedWitnessNumber); +}); + +it('string input and number input are the same', async () => { + const inputsString = { + x: '2', + y: '3', + }; + const inputsNumber = { + x: 2, + y: 3, + }; + + const solvedWitnessString = await new Noir(assert_lt_program).execute(inputsString); + const solvedWitnessNumber = await new Noir(assert_lt_program).execute(inputsNumber); + expect(solvedWitnessString).to.deep.equal(solvedWitnessNumber); +}); + +it('0x prefixed string input for inputs will throw', async () => { + const inputsHexPrefix = { + x: '0x2', + y: '0x3', + }; + + try { + await new Noir(assert_lt_program).execute(inputsHexPrefix); + expect.fail('Expected generatedWitness to throw, due to inputs being prefixed with 0x. Currently not supported'); + } catch (error) { + // Successfully errored due to 0x not being supported. Update this test once/if we choose + // to support 0x prefixed inputs. + } +}); + +describe('input validation', () => { + it('x should be a uint64 not a string', async () => { + const inputs = { + x: 'foo', + y: '3', + }; + + try { + await new Noir(assert_lt_program).execute(inputs); + expect.fail('Expected generatedWitness to throw, due to x not being convertible to a uint64'); + } catch (error) { + const knownError = error as Error; + expect(knownError.message).to.equal( + 'Expected witness values to be integers, provided value causes `invalid digit found in string` error', + ); + } + }); +}); diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml b/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml new file mode 100644 index 00000000000..f32ec18cae7 --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "assert_lt" +type = "bin" +authors = [""] +[dependencies] diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr b/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr new file mode 100644 index 00000000000..5a20a92048f --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr @@ -0,0 +1,11 @@ +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"); + + // A dynamic assertion message is used to show that noirJS will ignore the call and continue execution + // The assertion passes and thus the foreign call for resolving an assertion message should not be called. + assert(x < y, f"Expected x < y but got {x} < {y}"); + + assert(x < y); + x + y +} diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/Nargo.toml b/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/Nargo.toml new file mode 100644 index 00000000000..765f632ff74 --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_msg_runtime" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file 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 new file mode 100644 index 00000000000..0bcd5c58c24 --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: u64, y: pub u64) { + // 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/databus/Nargo.toml b/tooling/noir_js/test/noir_compiled_examples/databus/Nargo.toml new file mode 100644 index 00000000000..d484b80325e --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/databus/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "databus" +type = "bin" +authors = [""] +[dependencies] diff --git a/tooling/noir_js/test/noir_compiled_examples/databus/src/main.nr b/tooling/noir_js/test/noir_compiled_examples/databus/src/main.nr new file mode 100644 index 00000000000..ecc7794cf9e --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/databus/src/main.nr @@ -0,0 +1,12 @@ +fn main(mut x: u32, y: call_data(0) u32, z: call_data(0) [u32; 4]) -> return_data u32 { + let a = z[x]; + unsafe { + a + foo(y) + } +} + +// Use an unconstrained function to force the compiler to avoid inlining +unconstrained fn foo(x: u32) -> u32 { + x + 1 +} + 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/test/noir_compiled_examples/readme.md b/tooling/noir_js/test/noir_compiled_examples/readme.md new file mode 100644 index 00000000000..26c571850ae --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/readme.md @@ -0,0 +1,3 @@ +## Why + +While we do not automatically pull the .json files from .artifacts, we have these hard-coded versions of examples. diff --git a/tooling/noir_js/tsc-multi.json b/tooling/noir_js/tsc-multi.json new file mode 100644 index 00000000000..af26d1e4aa6 --- /dev/null +++ b/tooling/noir_js/tsc-multi.json @@ -0,0 +1,7 @@ +{ + "targets": [ + { "extname": ".cjs", "module": "commonjs" }, + { "extname": ".mjs", "module": "esnext" } + ], + "projects": ["packages/*/tsconfig.json"] +} \ No newline at end of file diff --git a/tooling/noir_js/tsconfig.json b/tooling/noir_js/tsconfig.json new file mode 100644 index 00000000000..0dbc5204556 --- /dev/null +++ b/tooling/noir_js/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "esnext", + "declaration": true, + "module": "ESNext", + "moduleResolution": "node", + "outDir": "./lib", + "esModuleInterop": true, + "resolveJsonModule": true, + "strict": true, + "noImplicitAny": false, + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules"], + "references": [ + { + "path": "../noir_js_types" + }, + ] +} diff --git a/tooling/noir_js_types/.eslintignore b/tooling/noir_js_types/.eslintignore new file mode 100644 index 00000000000..3c3629e647f --- /dev/null +++ b/tooling/noir_js_types/.eslintignore @@ -0,0 +1 @@ +node_modules diff --git a/tooling/noir_js_types/.eslintrc.cjs b/tooling/noir_js_types/.eslintrc.cjs new file mode 100644 index 00000000000..5a2cc7f1ec0 --- /dev/null +++ b/tooling/noir_js_types/.eslintrc.cjs @@ -0,0 +1,3 @@ +module.exports = { + extends: ['../../.eslintrc.js'], +}; diff --git a/tooling/noir_js_types/.gitignore b/tooling/noir_js_types/.gitignore new file mode 100644 index 00000000000..e92523b6247 --- /dev/null +++ b/tooling/noir_js_types/.gitignore @@ -0,0 +1,3 @@ +lib + +*.tsbuildinfo diff --git a/tooling/noir_js_types/.prettierrc b/tooling/noir_js_types/.prettierrc new file mode 100644 index 00000000000..ef937f9697a --- /dev/null +++ b/tooling/noir_js_types/.prettierrc @@ -0,0 +1,6 @@ +{ + "parser": "typescript", + "printWidth": 120, + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/tooling/noir_js_types/package.json b/tooling/noir_js_types/package.json new file mode 100644 index 00000000000..057ff29ef25 --- /dev/null +++ b/tooling/noir_js_types/package.json @@ -0,0 +1,48 @@ +{ + "name": "@noir-lang/types", + "contributors": [ + "The Noir Team " + ], + "packageManager": "yarn@3.5.1", + "version": "1.0.0-beta.1", + "license": "(MIT OR Apache-2.0)", + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "tooling/noir_js_types", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, + "files": [ + "lib", + "package.json" + ], + "main": "lib/cjs/types.js", + "module": "lib/esm/types.js", + "types": "lib/esm/types.d.ts", + "scripts": { + "build:esm": "tsc", + "build:cjs": "tsc --module CommonJS --outDir lib/cjs", + "build": "yarn run build:cjs && yarn run build:esm", + "nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", + "publish": "echo 📡 publishing `$npm_package_name` && yarn npm publish", + "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0", + "clean": "rm -rf ./lib" + }, + "exports": { + ".": { + "import": "./lib/esm/types.js", + "require": "./lib/cjs/types.js", + "types": "./lib/esm/types.d.ts" + } + }, + "devDependencies": { + "@types/prettier": "^3", + "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 new file mode 100644 index 00000000000..0cfe5d05a17 --- /dev/null +++ b/tooling/noir_js_types/src/types.ts @@ -0,0 +1,98 @@ +export type Field = string | number | boolean; +export type InputValue = Field | InputMap | InputValue[]; +export type InputMap = { [key: string]: InputValue }; + +export type Visibility = 'public' | 'private' | 'databus'; +export type Sign = 'unsigned' | 'signed'; +export type AbiType = + | { kind: 'field' } + | { kind: 'boolean' } + | { kind: 'string'; length: number } + | { kind: 'integer'; sign: Sign; width: number } + | { kind: 'array'; length: number; type: AbiType } + | { kind: 'tuple'; fields: AbiType[] } + | { kind: 'struct'; path: string; fields: { name: string; type: AbiType }[] }; + +export type AbiParameter = { + name: string; + type: AbiType; + visibility: Visibility; +}; + +export type AbiErrorType = + | { error_kind: 'string'; string: string } + | { + 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; + +export type Abi = { + parameters: AbiParameter[]; + return_type: { abi_type: AbiType; visibility: Visibility } | null; + error_types: Partial>; +}; + +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; + + /** + * + * @description Retrieves the artifacts from a proof in the Field format + */ + generateRecursiveProofArtifacts( + proofData: ProofData, + numOfPublicInputs: number, + ): Promise<{ + /** @description An array of Fields containing the proof */ + proofAsFields: string[]; + /** @description An array of Fields containing the verification key */ + vkAsFields: string[]; + /** @description A Field containing the verification key hash */ + vkHash: string; + }>; +} + +/** + * @description + * The representation of a proof + * */ +export type ProofData = { + /** @description Public inputs of a proof */ + publicInputs: string[]; + /** @description An byte array representing the proof */ + proof: Uint8Array; +}; + +/** + * @description + * The representation of a compiled circuit + * */ +export type CompiledCircuit = { + /** @description The bytecode of the circuit */ + bytecode: string; + /** @description ABI representation of the circuit */ + abi: Abi; +}; diff --git a/tooling/noir_js_types/tsconfig.json b/tooling/noir_js_types/tsconfig.json new file mode 100644 index 00000000000..0d5441cc5a2 --- /dev/null +++ b/tooling/noir_js_types/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "composite": true, + "declaration": true, + "module": "ESNext", + "moduleResolution": "node", + "outDir": "lib/esm", + "target": "ES2020", + "rootDir": "./src", + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/tooling/noirc_abi/Cargo.toml b/tooling/noirc_abi/Cargo.toml new file mode 100644 index 00000000000..22114408e18 --- /dev/null +++ b/tooling/noirc_abi/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "noirc_abi" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[lints] +workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +acvm.workspace = true +iter-extended.workspace = true +noirc_printable_type.workspace = true +toml.workspace = true +serde_json = "1.0" +serde.workspace = true +thiserror.workspace = true +num-bigint = "0.4" +num-traits = "0.2" + +[dev-dependencies] +strum.workspace = true +strum_macros.workspace = true +proptest.workspace = true +proptest-derive.workspace = true + +[features] +bn254 = ["acvm/bn254"] +bls12_381 = ["acvm/bls12_381"] diff --git a/tooling/noirc_abi/proptest-regressions/input_parser/json.txt b/tooling/noirc_abi/proptest-regressions/input_parser/json.txt new file mode 100644 index 00000000000..19de8eeaf48 --- /dev/null +++ b/tooling/noirc_abi/proptest-regressions/input_parser/json.txt @@ -0,0 +1,7 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc b3f9ae88d54944ca274764f4d99a2023d4b0ac09beb89bc599cbba1e45dd3620 # shrinks to (typ, value) = (Integer { sign: Signed, width: 1 }, -1) diff --git a/tooling/noirc_abi/proptest-regressions/input_parser/toml.txt b/tooling/noirc_abi/proptest-regressions/input_parser/toml.txt new file mode 100644 index 00000000000..1448cb67ef1 --- /dev/null +++ b/tooling/noirc_abi/proptest-regressions/input_parser/toml.txt @@ -0,0 +1,9 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 9d200afb8f5c01e3414d24eebe1436a7eef5377a46a9a9235aaa7f81e0b33656 # shrinks to (typ, value) = (Integer { sign: Signed, width: 8 }, -1) +cc 7fd29637e5566d819992185c1a95438e9949a555928a911b3918eed2e3f7a1fd # shrinks to (typ, value) = (Integer { sign: Signed, width: 64 }, -1) +cc 8ecbda39d887674b53ca23a861ac30fbb10c123bb70c57e69b336c86a3d9dea8 # shrinks to (abi, input_map) = (Abi { parameters: [AbiParameter { name: "¡", typ: Struct { path: "�)\u{1b}=�?Ⱥ\u{59424}?{\u{e4d5e}%Ѩ/Q\u{36a17}/*\";\u{b}&iC_\u{d313f}S\u{1b}\u{9dfec}\r/\u{10530d}", fields: [("?p*\"/\u{202e}\u{6f038}\u{537ca}.y@~𘛶?4\u{1b}*", Field), (".Ⱥ/$\u{7f}\u{103c06}%\\\u{202e}][0\u{88479}]\"*~\u{36fd5}\u{5}\u{feff}]{/", Tuple { fields: [String { length: 937 }] }), ("r\u{ac3a5}&:", Boolean), ("$d6🕴/:|�\u{37f8b}\r\u{a13b7}C$𲁹\\&\u{f8712}?\u{db61c}t%\u{57be1}\0", Field), ("/\u{6378b}\u{a426c}¥\u{7}/\u{fcb29}$\u{53c6b}\u{12d6f}\u{12bd3}.\u{f2f82}\u{8613e}*$\u{fd32f}\u{e29f7}\0𨺉'¬\"1", Struct { path: "\\\u{4a5ac}<\u{9e505}\u{4f3af}🕴&?<:^\u{7}\u{88}\u{3e1ff}(¥\u{531f3}K{:¥𦺀", fields: [("n\0Ѩ/\u{1b}𥐰\u{a4906}�¥`{\u{389d4}`1\u{7708a})\u{3dac4}8\u{93e5f}㒭\\\"\u{e6824}\u{b}Ѩ\u{88946}Ⱥ{", Integer { sign: Signed, width: 127 })] }), ("¥🕴\u{1b}¥🕴=sR\0\u{35f36}\u{867dc}>ä\u{202e}f:BȺ?:``*·¥\u{74ca5}\"", Tuple { fields: [Boolean, Field, String { length: 205 }, String { length: 575 }, Integer { sign: Signed, width: 124 }, String { length: 923 }, String { length: 294 }] })] }, visibility: Public }], return_type: None, error_types: {} }, {"¡": Struct({"$d6🕴/:|�\u{37f8b}\r\u{a13b7}C$𲁹\\&\u{f8712}?\u{db61c}t%\u{57be1}\0": Field(-8275115097504119425402713293372777967031130481426075481525511323101167533940), ".Ⱥ/$\u{7f}\u{103c06}%\\\u{202e}][0\u{88479}]\"*~\u{36fd5}\u{5}\u{feff}]{/": Vec([String("A \0A 0 aA0 a0aa00 A\000 0 \0\0aA\0\0a \0 \0a 0A\0A\0 Aa0aAA0A\0aa\00 0\0\0\0\0\00a Aa0 \0 a A0 \0AA0A Aa Aa\00aAaAaaA0A0 aA0 \0 Aa\00 \0000AAA a \0AAaaA\0\0a A0a0AA\0aA00 aA a0A\0AAa0a\0A0a\0\0A0A \00Aaaaa a A AO.*D\r.`bD4a\n*\u{15}\\B\"ace.8&A\t[AV8w<\u{18}\"\u{f}4`^Q\u{1b}U*$Z/\0\u{b}]qw${`\"=X&A\\\u{e}%`\\:\"$\u{1}.(6_C:\u{7}a`V=N**\u{1b})#Y\u{7f}#\u{b}$l\t}.Mns5!\t*$g\u{18}\rC\u{11}\"$=\u{7}.?&\u{1}yW\t.Y|<6\u{12}\u{e}/4JJ*&/V$`\"&`x#R\np\\%'*\n:P\0K\u{b}*`\r7Ym\t_\u{b}=$\u{16}`0v\u{7f}'NV^N4J<9=G*A:!b\u{1c}:'c{ST&z![\u{7f}/.={E*pmaWC\u{7f}7p{<\"']\u{8}?`\u{1b}\"\\\u{1}$\u{18}/!\u{16}-\t:E7CUs%_qw*xf.S\t\u{4}'=\"&%t'\u{1f}\u{7f}\u{b}$.=f\u{6}\"$A}xV_$\u{1a}nH\n\u{1b}?<&\n\u{15}U\\-b\u{1d}|\u{b}\u{2}t \rwA{L\u{11}\u{6}\u{10}\0\u{1b}G[x?&Yi?&7\u{b}?\r\u{1f}b\\$=\u{b}x& Q/\t\u{4}|X\"7\"{\0\0j'.\0\\e1zR.\u{c}\n<\u{b}Q*R+y8\u{19}(o\u{1f}@m\nt+\u{7f}Q\\+.Rn?\u{17}UZ\"$\u{b}/\0B=9=\t{\u{8}qZ&`!:D{\u{6}IO.H\u{7f}:?/3@\r\u{1b}oä\u{202e}f:BȺ?:``*·¥\u{74ca5}\"": Vec([Field(1), Field(8822392870083219098626030699076694602179106416928939583840848325203494062169), String("*TXn;{}\"_)_9\nk\\#ts\u{10}%\\c\n/2._::Oj*\u{7f}\0\r&PUMl\u{10}$/u?L}\u{7f}*P&<%=\u{7}S#%A\n \u{e}\\#v!\"\nepRp.{vH{&@\t\u{1f}\u{b}?=T\u{f}\"B\u{11}\n/{HY.\u{16}\n\nj<&\u{3}{f\n/9J*&x.$/,\r\0\u{1c}'\u{5}\u{13}\u{1b}`T\0`\n&/&\u{15}\u{b}w:{SK\u{7f}\\apR%/'0`0\n'd$$\u{7f}Vs\t<{\nDTT\\F\n\u{15}y.\\\t*-)&D$*u\u{b}\u{1b}?{\u{b}/\n\u{7f}0*.7\0\n:\u{b}.rSk<6~>{#"), String(".\"JA%q6i\ra/:F\u{16}?q<\t\rN\\13?H<;?{`\u{1d}p{.\"5?*@'N\"\u{1a}P,\u{1b}\u{7f}c+dt5':Y\u{1b}k/G>k/eM$XIX')\u{1b}'&\u{7f}\\\r\u{1b}`'P_.\n.?\0p`Y\u{c}`._\u{b}B\0\ng/*v$jfJ:\u{c}\u{1b}Pv}xn7ph@#{_<{.JD?r%'E\n7s9n/],u![;%*\u{2}{y`MgRdok8\"%<*>*{GyFJ}?\0W%#\0\u{1b}\u{7f}\u{16}G:\t=w\u{7f}:q\u{7f}:{k?\u{b}(:ca{$*1X/cw\u{1b}Z6I\rX\0\u{1b}(.^14\r\\=s\u{1b}w\u{3}F~\n\u{1e})/$0:=[\u{1},\\\\\tg\u{16}:],J`\0N\n\u{1b}\u{1b}\u{1b}{.xb\u{1a}\r'12#?e\\#/\tA\u{7f}\".\\Ke=\\?!v+P\u{17}\r\u{12}x.=A.`0<&?\niR/*WW\rnV)5vY.~\n _h\0&5f#\r\u{2}-S%\t s..\u{7f}!X}\"=\"?\u{5}y\u{4}`fr&R&d: 1Ht\"4`y_/S.71#{|%$%&ehy\u{16}J_\u{e}=:.%'\"N=J:\r:{&.\u{12}\u{b})&N\u{10}R_3;11\u{b}Qd<`<{?xF:~\"%<=<<\03:t??&\r;{\u{13}?__Y\u{6})\\k,vs?\n`G(*\n!\u{1b}[@z\0$?*yKLJh_\u{13}FkY'\\?T^\u{1f}$1n`'[\n\u{7f}\0+l\u{b}\u{1a}E\u{b}&(/\u{b}\rr\t:&\0+N'N:oC:*``IN\u{b}*.:\t$7+'*U:\t(iter: impl Iterator) { + let mut seen_values: HashSet = HashSet::default(); + for value in iter { + while seen_values.contains(value.as_str()) { + value.push('1'); + } + seen_values.insert(value.clone()); + } +} + +proptest::prop_compose! { + pub(super) fn arb_field_from_integer(bit_size: u32)(value: u128)-> FieldElement { + let width = (bit_size % 128).clamp(1, 127); + let max_value = 2u128.pow(width) - 1; + FieldElement::from(value.clamp(0, max_value)) + } +} + +fn arb_value_from_abi_type(abi_type: &AbiType) -> SBoxedStrategy { + match abi_type { + AbiType::Field => vec(any::(), 32) + .prop_map(|bytes| InputValue::Field(FieldElement::from_be_bytes_reduce(&bytes))) + .sboxed(), + AbiType::Integer { width, .. } => { + arb_field_from_integer(*width).prop_map(InputValue::Field).sboxed() + } + + AbiType::Boolean => { + any::().prop_map(|val| InputValue::Field(FieldElement::from(val))).sboxed() + } + + AbiType::String { length } => { + // Strings only allow ASCII characters as each character must be able to be represented by a single byte. + let string_regex = format!("[[:ascii:]]{{{length}}}"); + proptest::string::string_regex(&string_regex) + .expect("parsing of regex should always succeed") + .prop_map(InputValue::String) + .sboxed() + } + AbiType::Array { length, typ } => { + let length = *length as usize; + let elements = vec(arb_value_from_abi_type(typ), length..=length); + + elements.prop_map(InputValue::Vec).sboxed() + } + + AbiType::Struct { fields, .. } => { + let fields: Vec> = fields + .iter() + .map(|(name, typ)| (Just(name.clone()), arb_value_from_abi_type(typ)).sboxed()) + .collect(); + + fields + .prop_map(|fields| { + let fields: BTreeMap<_, _> = fields.into_iter().collect(); + InputValue::Struct(fields) + }) + .sboxed() + } + + AbiType::Tuple { fields } => { + let fields: Vec<_> = fields.iter().map(arb_value_from_abi_type).collect(); + fields.prop_map(InputValue::Vec).sboxed() + } + } +} + +fn arb_primitive_abi_type() -> SBoxedStrategy { + const MAX_STRING_LEN: u32 = 1000; + proptest::prop_oneof![ + Just(AbiType::Field), + Just(AbiType::Boolean), + any::<(Sign, u32)>().prop_map(|(sign, width)| { + let width = (width % 128).clamp(1, 127); + AbiType::Integer { sign, width } + }), + // restrict length of strings to avoid running out of memory + (1..MAX_STRING_LEN).prop_map(|length| AbiType::String { length }), + ] + .sboxed() +} + +pub(super) fn arb_abi_type() -> BoxedStrategy { + let leaf = arb_primitive_abi_type(); + + leaf.prop_recursive( + 8, // up to 8 levels deep + 256, // Shoot for maximum size of 256 nodes + 10, // We put up to 10 items per collection + |inner| { + prop_oneof![ + (1..10u32, inner.clone()) + .prop_map(|(length, typ)| { AbiType::Array { length, typ: Box::new(typ) } }) + .boxed(), + vec(inner.clone(), 1..10).prop_map(|fields| { AbiType::Tuple { fields } }).boxed(), + (".*", vec((".+", inner), 1..10)) + .prop_map(|(path, mut fields)| { + // Require that all field names are unique. + ensure_unique_strings(fields.iter_mut().map(|(field_name, _)| field_name)); + AbiType::Struct { path, fields } + }) + .boxed(), + ] + }, + ) + .boxed() +} + +fn arb_abi_param_and_value() -> BoxedStrategy<(AbiParameter, InputValue)> { + arb_abi_type() + .prop_flat_map(|typ| { + let value = arb_value_from_abi_type(&typ); + let param = arb_abi_param(typ); + (param, value) + }) + .boxed() +} + +fn arb_abi_param(typ: AbiType) -> SBoxedStrategy { + (".+", any::()) + .prop_map(move |(name, visibility)| AbiParameter { name, typ: typ.clone(), visibility }) + .sboxed() +} + +prop_compose! { + pub(super) fn arb_abi_and_input_map() + (mut parameters_with_values in vec(arb_abi_param_and_value(), 0..100), return_type: Option) + -> (Abi, InputMap) { + // Require that all parameter names are unique. + ensure_unique_strings(parameters_with_values.iter_mut().map(|(param_name,_)| &mut param_name.name)); + + let parameters = vecmap(¶meters_with_values, |(param, _)| param.clone()); + let input_map = btree_map(parameters_with_values, |(param, value)| (param.name, value)); + + (Abi { parameters, return_type, error_types: BTreeMap::default() }, input_map) + } +} diff --git a/tooling/noirc_abi/src/errors.rs b/tooling/noirc_abi/src/errors.rs new file mode 100644 index 00000000000..4209a9e218b --- /dev/null +++ b/tooling/noirc_abi/src/errors.rs @@ -0,0 +1,58 @@ +use crate::{ + input_parser::{InputTypecheckingError, InputValue}, + AbiType, +}; +use acvm::acir::native_types::Witness; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum InputParserError { + #[error("input file is badly formed, could not parse, {0}")] + ParseInputMap(String), + #[error("Expected witness values to be integers, provided value causes `{0}` error")] + ParseStr(String), + #[error("Could not parse hex value {0}")] + ParseHexStr(String), + #[error("cannot parse value into {0:?}")] + AbiTypeMismatch(AbiType), + #[error("Expected argument `{0}`, but none was found")] + MissingArgument(String), +} + +impl From for InputParserError { + fn from(err: toml::ser::Error) -> Self { + Self::ParseInputMap(err.to_string()) + } +} + +impl From for InputParserError { + fn from(err: toml::de::Error) -> Self { + Self::ParseInputMap(err.to_string()) + } +} + +impl From for InputParserError { + fn from(err: serde_json::Error) -> Self { + Self::ParseInputMap(err.to_string()) + } +} + +#[derive(Debug, Error)] +pub enum AbiError { + #[error("Received parameters not expected by ABI: {0:?}")] + UnexpectedParams(Vec), + #[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( + "Could not read witness value at index {witness_index:?} (required for parameter \"{name}\")" + )] + MissingParamWitnessValue { name: String, witness_index: Witness }, + #[error("Attempted to write to witness index {0:?} but it is already initialized to a different value")] + InconsistentWitnessAssignment(Witness), + #[error("The return value is expected to be a {return_type:?} but found incompatible value {value:?}")] + ReturnTypeMismatch { return_type: AbiType, value: InputValue }, + #[error("No return value is expected but received {0:?}")] + UnexpectedReturnValue(InputValue), +} diff --git a/tooling/noirc_abi/src/input_parser/json.rs b/tooling/noirc_abi/src/input_parser/json.rs new file mode 100644 index 00000000000..a8ba83a3a65 --- /dev/null +++ b/tooling/noirc_abi/src/input_parser/json.rs @@ -0,0 +1,237 @@ +use super::{field_to_signed_hex, parse_str_to_field, parse_str_to_signed, InputValue}; +use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; +use acvm::{AcirField, FieldElement}; +use iter_extended::{try_btree_map, try_vecmap}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +pub(crate) fn parse_json( + input_string: &str, + abi: &Abi, +) -> Result, InputParserError> { + // Parse input.json into a BTreeMap. + let data: BTreeMap = serde_json::from_str(input_string)?; + + // Convert arguments to field elements. + let mut parsed_inputs = try_btree_map(abi.to_btree_map(), |(arg_name, abi_type)| { + // Check that json contains a value for each argument in the ABI. + let value = data + .get(&arg_name) + .ok_or_else(|| InputParserError::MissingArgument(arg_name.clone()))?; + + InputValue::try_from_json(value.clone(), &abi_type, &arg_name) + .map(|input_value| (arg_name, input_value)) + })?; + + // If the json file also includes a return value then we parse it as well. + // This isn't required as the prover calculates the return value itself. + if let (Some(return_type), Some(json_return_value)) = + (&abi.return_type, data.get(MAIN_RETURN_NAME)) + { + let return_value = InputValue::try_from_json( + json_return_value.clone(), + &return_type.abi_type, + MAIN_RETURN_NAME, + )?; + parsed_inputs.insert(MAIN_RETURN_NAME.to_owned(), return_value); + } + + Ok(parsed_inputs) +} + +pub(crate) fn serialize_to_json( + input_map: &BTreeMap, + abi: &Abi, +) -> Result { + let mut json_map = try_btree_map(abi.to_btree_map(), |(key, param_type)| { + JsonTypes::try_from_input_value(&input_map[&key], ¶m_type) + .map(|value| (key.to_owned(), value)) + })?; + + if let (Some(return_type), Some(return_value)) = + (&abi.return_type, input_map.get(MAIN_RETURN_NAME)) + { + let return_value = JsonTypes::try_from_input_value(return_value, &return_type.abi_type)?; + json_map.insert(MAIN_RETURN_NAME.to_owned(), return_value); + } + + let json_string = serde_json::to_string(&json_map)?; + + Ok(json_string) +} + +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +#[serde(untagged)] +pub enum JsonTypes { + // This is most likely going to be a hex string + // But it is possible to support UTF-8 + String(String), + // Just a regular integer, that can fit in 64 bits. + // + // The JSON spec does not specify any limit on the size of integer number types, + // however we restrict the allowable size. Values which do not fit in a u64 should be passed + // as a string. + Integer(u64), + // Simple boolean flag + Bool(bool), + // Array of JsonTypes + Array(Vec), + // Struct of JsonTypes + Table(BTreeMap), +} + +impl JsonTypes { + pub fn try_from_input_value( + value: &InputValue, + abi_type: &AbiType, + ) -> Result { + let json_value = match (value, abi_type) { + (InputValue::Field(f), AbiType::Integer { sign: crate::Sign::Signed, width }) => { + JsonTypes::String(field_to_signed_hex(*f, *width)) + } + (InputValue::Field(f), AbiType::Field | AbiType::Integer { .. }) => { + JsonTypes::String(Self::format_field_string(*f)) + } + (InputValue::Field(f), AbiType::Boolean) => JsonTypes::Bool(f.is_one()), + + (InputValue::Vec(vector), AbiType::Array { typ, .. }) => { + let array = + try_vecmap(vector, |value| JsonTypes::try_from_input_value(value, typ))?; + JsonTypes::Array(array) + } + + (InputValue::String(s), AbiType::String { .. }) => JsonTypes::String(s.to_string()), + + (InputValue::Struct(map), AbiType::Struct { fields, .. }) => { + let map_with_json_types = try_btree_map(fields, |(key, field_type)| { + JsonTypes::try_from_input_value(&map[key], field_type) + .map(|json_value| (key.to_owned(), json_value)) + })?; + JsonTypes::Table(map_with_json_types) + } + + (InputValue::Vec(vector), AbiType::Tuple { fields }) => { + let fields = try_vecmap(vector.iter().zip(fields), |(value, typ)| { + JsonTypes::try_from_input_value(value, typ) + })?; + JsonTypes::Array(fields) + } + + _ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())), + }; + Ok(json_value) + } + + /// This trims any leading zeroes. + /// A singular '0' will be prepended as well if the trimmed string has an odd length. + /// A hex string's length needs to be even to decode into bytes, as two digits correspond to + /// one byte. + fn format_field_string(field: FieldElement) -> String { + if field.is_zero() { + return "0x00".to_owned(); + } + let mut trimmed_field = field.to_hex().trim_start_matches('0').to_owned(); + if trimmed_field.len() % 2 != 0 { + trimmed_field = "0".to_owned() + &trimmed_field; + } + "0x".to_owned() + &trimmed_field + } +} + +impl InputValue { + pub fn try_from_json( + value: JsonTypes, + param_type: &AbiType, + arg_name: &str, + ) -> Result { + let input_value = match (value, param_type) { + (JsonTypes::String(string), AbiType::String { .. }) => InputValue::String(string), + (JsonTypes::String(string), AbiType::Integer { sign: crate::Sign::Signed, width }) => { + InputValue::Field(parse_str_to_signed(&string, *width)?) + } + ( + JsonTypes::String(string), + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean, + ) => InputValue::Field(parse_str_to_field(&string)?), + + ( + JsonTypes::Integer(integer), + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean, + ) => { + let new_value = FieldElement::from(i128::from(integer)); + + InputValue::Field(new_value) + } + + (JsonTypes::Bool(boolean), AbiType::Boolean) => InputValue::Field(boolean.into()), + + (JsonTypes::Array(array), AbiType::Array { typ, .. }) => { + let array_elements = + try_vecmap(array, |value| InputValue::try_from_json(value, typ, arg_name))?; + InputValue::Vec(array_elements) + } + + (JsonTypes::Table(table), AbiType::Struct { fields, .. }) => { + let native_table = try_btree_map(fields, |(field_name, abi_type)| { + // Check that json contains a value for each field of the struct. + let field_id = format!("{arg_name}.{field_name}"); + let value = table + .get(field_name) + .ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?; + InputValue::try_from_json(value.clone(), abi_type, &field_id) + .map(|input_value| (field_name.to_string(), input_value)) + })?; + + InputValue::Struct(native_table) + } + + (JsonTypes::Array(array), AbiType::Tuple { fields }) => { + let tuple_fields = try_vecmap(array.into_iter().zip(fields), |(value, typ)| { + InputValue::try_from_json(value, typ, arg_name) + })?; + InputValue::Vec(tuple_fields) + } + + (_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), + }; + + Ok(input_value) + } +} + +#[cfg(test)] +mod test { + use proptest::prelude::*; + + use crate::{ + arbitrary::arb_abi_and_input_map, + input_parser::{arbitrary::arb_signed_integer_type_and_value, json::JsonTypes, InputValue}, + }; + + use super::{parse_json, serialize_to_json}; + + proptest! { + #[test] + fn serializing_and_parsing_returns_original_input((abi, input_map) in arb_abi_and_input_map()) { + let json = serialize_to_json(&input_map, &abi).expect("should be serializable"); + let parsed_input_map = parse_json(&json, &abi).expect("should be parsable"); + + prop_assert_eq!(parsed_input_map, input_map); + } + + #[test] + fn signed_integer_serialization_roundtrip((typ, value) in arb_signed_integer_type_and_value()) { + let string_input = JsonTypes::String(value.to_string()); + let input_value = InputValue::try_from_json(string_input, &typ, "foo").expect("should be parsable"); + let JsonTypes::String(output_string) = JsonTypes::try_from_input_value(&input_value, &typ).expect("should be serializable") else { + panic!("wrong type output"); + }; + let output_number = if let Some(output_string) = output_string.strip_prefix("-0x") { + -i64::from_str_radix(output_string, 16).unwrap() + } else { + i64::from_str_radix(output_string.strip_prefix("0x").unwrap(), 16).unwrap() + }; + prop_assert_eq!(output_number, value); + } + } +} diff --git a/tooling/noirc_abi/src/input_parser/mod.rs b/tooling/noirc_abi/src/input_parser/mod.rs new file mode 100644 index 00000000000..b7732235eb2 --- /dev/null +++ b/tooling/noirc_abi/src/input_parser/mod.rs @@ -0,0 +1,456 @@ +use num_bigint::{BigInt, BigUint}; +use num_traits::{Num, Zero}; +use std::collections::{BTreeMap, HashSet}; +use thiserror::Error; + +use acvm::{AcirField, FieldElement}; +use serde::Serialize; + +use crate::errors::InputParserError; +use crate::{Abi, AbiType}; + +pub mod json; +mod toml; + +/// This is what all formats eventually transform into +/// For example, a toml file will parse into TomlTypes +/// and those TomlTypes will be mapped to Value +#[derive(Debug, Clone, Serialize, PartialEq)] +pub enum InputValue { + Field(FieldElement), + String(String), + Vec(Vec), + 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 + pub(crate) fn find_type_mismatch( + &self, + abi_param: &AbiType, + path: String, + ) -> Result<(), InputTypecheckingError> { + match (self, abi_param) { + (InputValue::Field(_), AbiType::Field) => Ok(()), + (InputValue::Field(field_element), AbiType::Integer { 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) => { + 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 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. + 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 }) => { + 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, .. }) => { + 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(), + }); + } + } + + 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(), + }); + } + + Ok(()) + } + + (InputValue::Vec(vec_elements), AbiType::Tuple { fields }) => { + if vec_elements.len() != fields.len() { + return Err(InputTypecheckingError::LengthMismatch { + path, + typ: abi_param.clone(), + value: self.clone(), + actual_length: vec_elements.len(), + expected_length: fields.len(), + }); + } + // 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. + _ => 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 +/// the initial witness values +#[cfg_attr(test, derive(strum_macros::EnumIter))] +pub enum Format { + Json, + Toml, +} + +impl Format { + pub fn ext(&self) -> &'static str { + match self { + Format::Json => "json", + Format::Toml => "toml", + } + } +} + +impl Format { + pub fn parse( + &self, + input_string: &str, + abi: &Abi, + ) -> Result, InputParserError> { + match self { + Format::Json => json::parse_json(input_string, abi), + Format::Toml => toml::parse_toml(input_string, abi), + } + } + + pub fn serialize( + &self, + input_map: &BTreeMap, + abi: &Abi, + ) -> Result { + match self { + Format::Json => json::serialize_to_json(input_map, abi), + Format::Toml => toml::serialize_to_toml(input_map, abi), + } + } +} + +#[cfg(test)] +mod serialization_tests { + use std::collections::BTreeMap; + + use acvm::{AcirField, FieldElement}; + use strum::IntoEnumIterator; + + use crate::{ + input_parser::InputValue, Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, Sign, + MAIN_RETURN_NAME, + }; + + use super::Format; + + #[test] + fn serialization_round_trip() { + let abi = Abi { + parameters: vec![ + AbiParameter { + name: "foo".into(), + typ: AbiType::Field, + visibility: AbiVisibility::Private, + }, + AbiParameter { + name: "signed_example".into(), + typ: AbiType::Integer { sign: Sign::Signed, width: 8 }, + visibility: AbiVisibility::Private, + }, + AbiParameter { + name: "bar".into(), + typ: AbiType::Struct { + path: "MyStruct".into(), + fields: vec![ + ("field1".into(), AbiType::Integer { sign: Sign::Unsigned, width: 8 }), + ( + "field2".into(), + AbiType::Array { length: 2, typ: Box::new(AbiType::Boolean) }, + ), + ], + }, + visibility: AbiVisibility::Private, + }, + ], + return_type: Some(AbiReturnType { + abi_type: AbiType::String { length: 5 }, + visibility: AbiVisibility::Public, + }), + error_types: Default::default(), + }; + + let input_map: BTreeMap = BTreeMap::from([ + ("foo".into(), InputValue::Field(FieldElement::one())), + ("signed_example".into(), InputValue::Field(FieldElement::from(240u128))), + ( + "bar".into(), + InputValue::Struct(BTreeMap::from([ + ("field1".into(), InputValue::Field(255u128.into())), + ( + "field2".into(), + InputValue::Vec(vec![ + InputValue::Field(true.into()), + InputValue::Field(false.into()), + ]), + ), + ])), + ), + (MAIN_RETURN_NAME.into(), InputValue::String("hello".to_owned())), + ]); + + for format in Format::iter() { + let serialized_inputs = format.serialize(&input_map, &abi).unwrap(); + + let reconstructed_input_map = format.parse(&serialized_inputs, &abi).unwrap(); + + assert_eq!(input_map, reconstructed_input_map); + } + } +} + +fn parse_str_to_field(value: &str) -> Result { + let big_num = if let Some(hex) = value.strip_prefix("0x") { + BigUint::from_str_radix(hex, 16) + } else { + BigUint::from_str_radix(value, 10) + }; + big_num.map_err(|err_msg| InputParserError::ParseStr(err_msg.to_string())).and_then(|bigint| { + if bigint < FieldElement::modulus() { + Ok(field_from_big_uint(bigint)) + } else { + Err(InputParserError::ParseStr(format!( + "Input exceeds field modulus. Values must fall within [0, {})", + FieldElement::modulus(), + ))) + } + }) +} + +fn parse_str_to_signed(value: &str, width: u32) -> Result { + let big_num = if let Some(hex) = value.strip_prefix("-0x") { + BigInt::from_str_radix(hex, 16).map(|value| -value) + } else if let Some(hex) = value.strip_prefix("0x") { + BigInt::from_str_radix(hex, 16) + } else { + BigInt::from_str_radix(value, 10) + }; + + big_num.map_err(|err_msg| InputParserError::ParseStr(err_msg.to_string())).and_then(|bigint| { + let modulus: BigInt = FieldElement::modulus().into(); + let bigint = if bigint.sign() == num_bigint::Sign::Minus { + BigInt::from(2).pow(width) + bigint + } else { + bigint + }; + if bigint.is_zero() || (bigint.sign() == num_bigint::Sign::Plus && bigint < modulus) { + Ok(field_from_big_int(bigint)) + } else { + Err(InputParserError::ParseStr(format!( + "Input exceeds field modulus. Values must fall within [0, {})", + FieldElement::modulus(), + ))) + } + }) +} + +fn field_from_big_uint(bigint: BigUint) -> FieldElement { + FieldElement::from_be_bytes_reduce(&bigint.to_bytes_be()) +} + +fn field_from_big_int(bigint: BigInt) -> FieldElement { + match bigint.sign() { + num_bigint::Sign::Minus => { + unreachable!( + "Unsupported negative value; it should only be called with a positive value" + ) + } + num_bigint::Sign::NoSign => FieldElement::zero(), + num_bigint::Sign::Plus => FieldElement::from_be_bytes_reduce(&bigint.to_bytes_be().1), + } +} + +fn field_to_signed_hex(f: FieldElement, bit_size: u32) -> String { + let f_u128 = f.to_u128(); + let max = 2_u128.pow(bit_size - 1) - 1; + if f_u128 > max { + let f = FieldElement::from(2_u128.pow(bit_size) - f_u128); + format!("-0x{}", f.to_hex()) + } else { + format!("0x{}", f.to_hex()) + } +} + +#[cfg(test)] +mod test { + use acvm::{AcirField, FieldElement}; + use num_bigint::BigUint; + + use super::{parse_str_to_field, parse_str_to_signed}; + + fn big_uint_from_field(field: FieldElement) -> BigUint { + BigUint::from_bytes_be(&field.to_be_bytes()) + } + + #[test] + fn parse_empty_str_fails() { + // Check that this fails appropriately rather than being treated as 0, etc. + assert!(parse_str_to_field("").is_err()); + } + + #[test] + fn parse_fields_from_strings() { + let fields = vec![ + FieldElement::zero(), + FieldElement::one(), + FieldElement::from(u128::MAX) + FieldElement::one(), + // Equivalent to `FieldElement::modulus() - 1` + -FieldElement::one(), + ]; + + for field in fields { + let hex_field = format!("0x{}", field.to_hex()); + let field_from_hex = parse_str_to_field(&hex_field).unwrap(); + assert_eq!(field_from_hex, field); + + let dec_field = big_uint_from_field(field).to_string(); + let field_from_dec = parse_str_to_field(&dec_field).unwrap(); + assert_eq!(field_from_dec, field); + } + } + + #[test] + fn rejects_noncanonical_fields() { + let noncanonical_field = FieldElement::modulus().to_string(); + assert!(parse_str_to_field(&noncanonical_field).is_err()); + } + + #[test] + fn test_parse_str_to_signed() { + let value = parse_str_to_signed("1", 8).unwrap(); + assert_eq!(value, FieldElement::from(1_u128)); + + let value = parse_str_to_signed("-1", 8).unwrap(); + assert_eq!(value, FieldElement::from(255_u128)); + + let value = parse_str_to_signed("-1", 16).unwrap(); + assert_eq!(value, FieldElement::from(65535_u128)); + } +} + +#[cfg(test)] +mod arbitrary { + use proptest::prelude::*; + + use crate::{AbiType, Sign}; + + pub(super) fn arb_signed_integer_type_and_value() -> BoxedStrategy<(AbiType, i64)> { + (2u32..=64) + .prop_flat_map(|width| { + let typ = Just(AbiType::Integer { width, sign: Sign::Signed }); + let value = if width == 64 { + // Avoid overflow + i64::MIN..i64::MAX + } else { + -(2i64.pow(width - 1))..(2i64.pow(width - 1) - 1) + }; + (typ, value) + }) + .boxed() + } +} diff --git a/tooling/noirc_abi/src/input_parser/toml.rs b/tooling/noirc_abi/src/input_parser/toml.rs new file mode 100644 index 00000000000..6f2be68a0c4 --- /dev/null +++ b/tooling/noirc_abi/src/input_parser/toml.rs @@ -0,0 +1,222 @@ +use super::{field_to_signed_hex, parse_str_to_field, parse_str_to_signed, InputValue}; +use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; +use acvm::{AcirField, FieldElement}; +use iter_extended::{try_btree_map, try_vecmap}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +pub(crate) fn parse_toml( + input_string: &str, + abi: &Abi, +) -> Result, InputParserError> { + // Parse input.toml into a BTreeMap. + let data: BTreeMap = toml::from_str(input_string)?; + + // Convert arguments to field elements. + let mut parsed_inputs = try_btree_map(abi.to_btree_map(), |(arg_name, abi_type)| { + // Check that toml contains a value for each argument in the ABI. + let value = data + .get(&arg_name) + .ok_or_else(|| InputParserError::MissingArgument(arg_name.clone()))?; + + InputValue::try_from_toml(value.clone(), &abi_type, &arg_name) + .map(|input_value| (arg_name, input_value)) + })?; + + // If the toml file also includes a return value then we parse it as well. + // This isn't required as the prover calculates the return value itself. + if let (Some(return_type), Some(toml_return_value)) = + (&abi.return_type, data.get(MAIN_RETURN_NAME)) + { + let return_value = InputValue::try_from_toml( + toml_return_value.clone(), + &return_type.abi_type, + MAIN_RETURN_NAME, + )?; + parsed_inputs.insert(MAIN_RETURN_NAME.to_owned(), return_value); + } + + Ok(parsed_inputs) +} + +pub(crate) fn serialize_to_toml( + input_map: &BTreeMap, + abi: &Abi, +) -> Result { + let mut toml_map = try_btree_map(abi.to_btree_map(), |(key, param_type)| { + TomlTypes::try_from_input_value(&input_map[&key], ¶m_type) + .map(|toml_value| (key.clone(), toml_value)) + })?; + + if let (Some(return_type), Some(return_value)) = + (&abi.return_type, input_map.get(MAIN_RETURN_NAME)) + { + let return_value = TomlTypes::try_from_input_value(return_value, &return_type.abi_type)?; + toml_map.insert(MAIN_RETURN_NAME.to_owned(), return_value); + } + + let toml_string = toml::to_string(&toml_map)?; + + Ok(toml_string) +} + +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +#[serde(untagged)] +enum TomlTypes { + // This is most likely going to be a hex string + // But it is possible to support UTF-8 + String(String), + // Just a regular integer, that can fit in 64 bits + // Note that the toml spec specifies that all numbers are represented as `i64`s. + Integer(u64), + // Simple boolean flag + Bool(bool), + // Array of TomlTypes + Array(Vec), + // Struct of TomlTypes + Table(BTreeMap), +} + +impl TomlTypes { + fn try_from_input_value( + value: &InputValue, + abi_type: &AbiType, + ) -> Result { + let toml_value = match (value, abi_type) { + (InputValue::Field(f), AbiType::Integer { sign: crate::Sign::Signed, width }) => { + TomlTypes::String(field_to_signed_hex(*f, *width)) + } + (InputValue::Field(f), AbiType::Field | AbiType::Integer { .. }) => { + let f_str = format!("0x{}", f.to_hex()); + TomlTypes::String(f_str) + } + (InputValue::Field(f), AbiType::Boolean) => TomlTypes::Bool(f.is_one()), + + (InputValue::Vec(vector), AbiType::Array { typ, .. }) => { + let array = + try_vecmap(vector, |value| TomlTypes::try_from_input_value(value, typ))?; + TomlTypes::Array(array) + } + + (InputValue::String(s), AbiType::String { .. }) => TomlTypes::String(s.to_string()), + + (InputValue::Struct(map), AbiType::Struct { fields, .. }) => { + let map_with_toml_types = try_btree_map(fields, |(key, field_type)| { + TomlTypes::try_from_input_value(&map[key], field_type) + .map(|toml_value| (key.to_owned(), toml_value)) + })?; + TomlTypes::Table(map_with_toml_types) + } + + (InputValue::Vec(vector), AbiType::Tuple { fields }) => { + let fields = try_vecmap(vector.iter().zip(fields), |(value, typ)| { + TomlTypes::try_from_input_value(value, typ) + })?; + TomlTypes::Array(fields) + } + + _ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())), + }; + Ok(toml_value) + } +} + +impl InputValue { + fn try_from_toml( + value: TomlTypes, + param_type: &AbiType, + arg_name: &str, + ) -> Result { + let input_value = match (value, param_type) { + (TomlTypes::String(string), AbiType::String { .. }) => InputValue::String(string), + + ( + TomlTypes::String(string), + AbiType::Field + | AbiType::Integer { sign: crate::Sign::Unsigned, .. } + | AbiType::Boolean, + ) => InputValue::Field(parse_str_to_field(&string)?), + (TomlTypes::String(string), AbiType::Integer { sign: crate::Sign::Signed, width }) => { + InputValue::Field(parse_str_to_signed(&string, *width)?) + } + ( + TomlTypes::Integer(integer), + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean, + ) => { + let new_value = FieldElement::from(u128::from(integer)); + + InputValue::Field(new_value) + } + + (TomlTypes::Bool(boolean), AbiType::Boolean) => InputValue::Field(boolean.into()), + + (TomlTypes::Array(array), AbiType::Array { typ, .. }) => { + let array_elements = + try_vecmap(array, |value| InputValue::try_from_toml(value, typ, arg_name))?; + InputValue::Vec(array_elements) + } + + (TomlTypes::Table(table), AbiType::Struct { fields, .. }) => { + let native_table = try_btree_map(fields, |(field_name, abi_type)| { + // Check that json contains a value for each field of the struct. + let field_id = format!("{arg_name}.{field_name}"); + let value = table + .get(field_name) + .ok_or_else(|| InputParserError::MissingArgument(field_id.clone()))?; + InputValue::try_from_toml(value.clone(), abi_type, &field_id) + .map(|input_value| (field_name.to_string(), input_value)) + })?; + + InputValue::Struct(native_table) + } + + (TomlTypes::Array(array), AbiType::Tuple { fields }) => { + let tuple_fields = try_vecmap(array.into_iter().zip(fields), |(value, typ)| { + InputValue::try_from_toml(value, typ, arg_name) + })?; + InputValue::Vec(tuple_fields) + } + + (_, _) => return Err(InputParserError::AbiTypeMismatch(param_type.clone())), + }; + + Ok(input_value) + } +} + +#[cfg(test)] +mod test { + use proptest::prelude::*; + + use crate::{ + arbitrary::arb_abi_and_input_map, + input_parser::{arbitrary::arb_signed_integer_type_and_value, toml::TomlTypes, InputValue}, + }; + + use super::{parse_toml, serialize_to_toml}; + + proptest! { + #[test] + fn serializing_and_parsing_returns_original_input((abi, input_map) in arb_abi_and_input_map()) { + let toml = serialize_to_toml(&input_map, &abi).expect("should be serializable"); + let parsed_input_map = parse_toml(&toml, &abi).expect("should be parsable"); + + prop_assert_eq!(parsed_input_map, input_map); + } + + #[test] + fn signed_integer_serialization_roundtrip((typ, value) in arb_signed_integer_type_and_value()) { + let string_input = TomlTypes::String(value.to_string()); + let input_value = InputValue::try_from_toml(string_input.clone(), &typ, "foo").expect("should be parsable"); + let TomlTypes::String(output_string) = TomlTypes::try_from_input_value(&input_value, &typ).expect("should be serializable") else { + panic!("wrong type output"); + }; + let output_number = if let Some(output_string) = output_string.strip_prefix("-0x") { + -i64::from_str_radix(output_string, 16).unwrap() + } else { + i64::from_str_radix(output_string.strip_prefix("0x").unwrap(), 16).unwrap() + }; + prop_assert_eq!(output_number, value); + } + } +} diff --git a/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs new file mode 100644 index 00000000000..5f5f3748bc4 --- /dev/null +++ b/tooling/noirc_abi/src/lib.rs @@ -0,0 +1,522 @@ +#![forbid(unsafe_code)] +#![warn(unused_crate_dependencies, unused_extern_crates)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] + +use acvm::{ + 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_printable_type::{PrintableType, PrintableValue, PrintableValueDisplay}; +use serde::{Deserialize, Serialize}; +use std::borrow::Borrow; +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. +// +// This ABI has nothing to do with ACVM or ACIR. Although they implicitly have a relationship + +#[cfg(test)] +mod arbitrary; + +pub mod errors; +pub mod input_parser; +mod printable_type; +mod serialization; + +pub use printable_type::decode_value as decode_printable_value; + +/// A map from the fields in an TOML/JSON file which correspond to some ABI to their values +pub type InputMap = BTreeMap; + +pub const MAIN_RETURN_NAME: &str = "return"; + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag = "kind", rename_all = "lowercase")] +/// Types that are allowed in the (main function in binary) +/// +/// we use this separation so that we can have types like Strings +/// without needing to introduce this in the Noir types +/// +/// NOTE: If Strings are introduced as a native type, the translation will +/// be straightforward. Whether exotic types like String will be natively supported +/// depends on the types of programs that users want to do. I don't envision string manipulation +/// in programs, however it is possible to support, with many complications like encoding character set +/// support. +#[derive(Hash)] +pub enum AbiType { + Field, + Array { + length: u32, + #[serde(rename = "type")] + typ: Box, + }, + Integer { + sign: Sign, + width: u32, + }, + Boolean, + Struct { + path: String, + #[serde( + serialize_with = "serialization::serialize_struct_fields", + deserialize_with = "serialization::deserialize_struct_fields" + )] + fields: Vec<(String, AbiType)>, + }, + Tuple { + fields: Vec, + }, + String { + length: u32, + }, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] +#[serde(rename_all = "lowercase")] +/// Represents whether the parameter is public or known only to the prover. +pub enum AbiVisibility { + Public, + // Constants are not allowed in the ABI for main at the moment. + // Constant, + Private, + DataBus, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] +#[serde(rename_all = "lowercase")] +pub enum Sign { + Unsigned, + Signed, +} + +impl AbiType { + /// Returns the number of field elements required to represent the type once encoded. + pub fn field_count(&self) -> u32 { + match self { + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean => 1, + 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, + } + } +} + +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 } + } + } + } +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Hash)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] +/// An argument or return value of the circuit's `main` function. +pub struct AbiParameter { + pub name: String, + #[serde(rename = "type")] + #[cfg_attr(test, proptest(strategy = "arbitrary::arb_abi_type()"))] + pub typ: AbiType, + pub visibility: AbiVisibility, +} + +impl AbiParameter { + pub fn is_public(&self) -> bool { + self.visibility == AbiVisibility::Public + } +} + +#[derive(Clone, Debug, Serialize, Deserialize, Hash)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] +pub struct AbiReturnType { + #[cfg_attr(test, proptest(strategy = "arbitrary::arb_abi_type()"))] + pub abi_type: AbiType, + pub visibility: AbiVisibility, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize, Hash)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] +pub struct Abi { + /// An ordered list of the arguments to the program's `main` function, specifying their types and visibility. + pub parameters: Vec, + pub return_type: Option, + #[cfg_attr(test, proptest(strategy = "proptest::prelude::Just(BTreeMap::from([]))"))] + pub error_types: BTreeMap, +} + +impl Abi { + pub fn parameter_names(&self) -> Vec<&String> { + self.parameters.iter().map(|x| &x.name).collect() + } + + pub fn num_parameters(&self) -> usize { + self.parameters.len() + } + + /// Returns the number of field elements required to represent the ABI's input once encoded. + pub fn field_count(&self) -> u32 { + self.parameters.iter().map(|param| param.typ.field_count()).sum() + } + + /// Returns whether any values are needed to be made public for verification. + pub fn has_public_inputs(&self) -> bool { + let has_public_args = self.parameters.iter().any(|param| param.is_public()); + let has_public_return = self + .return_type + .as_ref() + .map_or(false, |typ| matches!(typ.visibility, AbiVisibility::Public)); + has_public_args || has_public_return + } + + /// Returns `true` if the ABI contains no parameters or return value. + pub fn is_empty(&self) -> bool { + self.return_type.is_none() && self.parameters.is_empty() + } + + pub fn to_btree_map(&self) -> BTreeMap { + let mut map = BTreeMap::new(); + for param in self.parameters.iter() { + map.insert(param.name.clone(), param.typ.clone()); + } + map + } + + /// Encode a set of inputs as described in the ABI into a `WitnessMap`. + pub fn encode( + &self, + input_map: &InputMap, + return_value: Option, + ) -> Result, AbiError> { + // Check that no extra witness values have been provided. + let param_names = self.parameter_names(); + if param_names.len() < input_map.len() { + let unexpected_params: Vec = + input_map.keys().filter(|param| !param_names.contains(param)).cloned().collect(); + return Err(AbiError::UnexpectedParams(unexpected_params)); + } + + // First encode each input separately, performing any input validation. + let mut encoded_inputs: Vec> = self + .parameters + .iter() + .map(|param| { + let value = input_map + .get(¶m.name) + .ok_or_else(|| AbiError::MissingParam(param.name.clone()))? + .clone(); + + value.find_type_mismatch(¶m.typ, param.name.clone())?; + + Self::encode_value(value, ¶m.typ) + }) + .collect::>()?; + + // When encoding public inputs to be passed to the verifier, the user can must provide a return value + // to be inserted into the witness map. This is not needed when generating a witness when proving the circuit. + match (&self.return_type, return_value) { + (Some(AbiReturnType { abi_type: return_type, .. }), Some(return_value)) => { + if !return_value.matches_abi(return_type) { + return Err(AbiError::ReturnTypeMismatch { + return_type: return_type.clone(), + value: return_value, + }); + } + let encoded_return_fields = Self::encode_value(return_value, return_type)?; + encoded_inputs.push(encoded_return_fields); + } + (None, Some(return_value)) => { + return Err(AbiError::UnexpectedReturnValue(return_value)) + } + // We allow not passing a return value despite the circuit defining one + // in order to generate the initial partial witness. + (_, None) => {} + } + + // Write input field elements into witness map. + let witness_map: BTreeMap = encoded_inputs + .into_iter() + .flatten() + .enumerate() + .map(|(index, field_element)| (Witness(index as u32), field_element)) + .collect::>(); + + Ok(witness_map.into()) + } + + fn encode_value(value: InputValue, abi_type: &AbiType) -> Result, AbiError> { + let mut encoded_value = Vec::new(); + match (value, abi_type) { + (InputValue::Field(elem), _) => encoded_value.push(elem), + + (InputValue::Vec(vec_elements), AbiType::Array { typ, .. }) => { + for elem in vec_elements { + encoded_value.extend(Self::encode_value(elem, typ)?); + } + } + + (InputValue::String(string), _) => { + let str_as_fields = + string.bytes().map(|byte| FieldElement::from_be_bytes_reduce(&[byte])); + encoded_value.extend(str_as_fields); + } + + (InputValue::Struct(object), AbiType::Struct { fields, .. }) => { + for (field, typ) in fields { + encoded_value.extend(Self::encode_value(object[field].clone(), typ)?); + } + } + (InputValue::Vec(vec_elements), AbiType::Tuple { fields }) => { + for (value, typ) in vec_elements.into_iter().zip(fields) { + encoded_value.extend(Self::encode_value(value, typ)?); + } + } + _ => unreachable!("value should have already been checked to match abi type"), + } + Ok(encoded_value) + } + + /// Decode a `WitnessMap` into the types specified in the ABI. + pub fn decode( + &self, + witness_map: &WitnessMap, + ) -> Result<(InputMap, Option), AbiError> { + let mut pointer: u32 = 0; + let public_inputs_map = + try_btree_map(self.parameters.clone(), |AbiParameter { name, typ, .. }| { + let num_fields = typ.field_count(); + let param_witness_values = try_vecmap(0..num_fields, |index| { + let witness_index = Witness(pointer + index); + witness_map + .get(&witness_index) + .ok_or_else(|| AbiError::MissingParamWitnessValue { + name: name.clone(), + witness_index, + }) + .copied() + })?; + pointer += num_fields; + + decode_value(&mut param_witness_values.into_iter(), &typ) + .map(|input_value| (name.clone(), input_value)) + })?; + + // We also attempt to decode the circuit's return value from `witness_map`. + let return_value = if let Some(return_type) = &self.return_type { + if let Ok(return_witness_values) = + try_vecmap(0..return_type.abi_type.field_count(), |index| { + let witness_index = Witness(pointer + index); + witness_map + .get(&witness_index) + .ok_or_else(|| AbiError::MissingParamWitnessValue { + name: MAIN_RETURN_NAME.to_string(), + witness_index, + }) + .copied() + }) + { + 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. + // If a return value is expected, this should be checked for by the user. + None + } + } else { + None + }; + + Ok((public_inputs_map, return_value)) + } +} + +pub fn decode_value( + field_iterator: &mut impl Iterator, + value_type: &AbiType, +) -> Result { + // This function assumes that `field_iterator` contains enough `FieldElement`s in order to decode a `value_type` + // `Abi.decode` enforces that the encoded inputs matches the expected length defined by the ABI so this is safe. + let value = match value_type { + AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean => { + let field_element = field_iterator.next().unwrap(); + + InputValue::Field(field_element) + } + AbiType::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)?); + } + + InputValue::Vec(array_elements) + } + AbiType::String { length } => { + let field_elements: Vec = field_iterator.take(*length as usize).collect(); + + InputValue::String(decode_string_value(&field_elements)) + } + AbiType::Struct { fields, .. } => { + let mut struct_map = BTreeMap::new(); + + for (field_key, param_type) in fields { + let field_value = decode_value(field_iterator, param_type)?; + + struct_map.insert(field_key.to_owned(), field_value); + } + + InputValue::Struct(struct_map) + } + AbiType::Tuple { fields } => { + let mut tuple_elements = Vec::with_capacity(fields.len()); + for field_typ in fields { + tuple_elements.push(decode_value(field_iterator, field_typ)?); + } + + InputValue::Vec(tuple_elements) + } + }; + + Ok(value) +} + +pub fn decode_string_value(field_elements: &[F]) -> String { + let string_as_slice = vecmap(field_elements, |e| { + let mut field_as_bytes = e.to_be_bytes(); + let char_byte = field_as_bytes.pop().unwrap(); // A character in a string is represented by a u8, thus we just want the last byte of the element + assert!(field_as_bytes.into_iter().all(|b| b == 0)); // Assert that the rest of the field element's bytes are empty + char_byte + }); + + let final_string = str::from_utf8(&string_as_slice).unwrap(); + final_string.to_owned() +} + +#[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, + }, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] +#[serde(tag = "error_kind", rename_all = "lowercase")] +pub enum AbiErrorType { + FmtString { length: u32, item_types: Vec }, + Custom(AbiType), + String { string: String }, +} + +pub fn display_abi_error( + fields: &[F], + error_type: AbiErrorType, +) -> PrintableValueDisplay { + match error_type { + AbiErrorType::FmtString { length, item_types } => { + let mut fields_iter = fields.iter().copied(); + let PrintableValue::String(string) = + decode_printable_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 = decode_printable_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 = decode_printable_value(&mut fields.iter().copied(), &printable_type); + PrintableValueDisplay::Plain(decoded, printable_type) + } + AbiErrorType::String { string } => { + let length = string.len() as u32; + PrintableValueDisplay::Plain( + PrintableValue::String(string), + PrintableType::String { length }, + ) + } + } +} + +#[cfg(test)] +mod test { + use proptest::prelude::*; + + use crate::arbitrary::arb_abi_and_input_map; + + proptest! { + #[test] + fn encoding_and_decoding_returns_original_witness_map((abi, input_map) in arb_abi_and_input_map()) { + let witness_map = abi.encode(&input_map, None).unwrap(); + let (decoded_inputs, return_value) = abi.decode(&witness_map).unwrap(); + + prop_assert_eq!(decoded_inputs, input_map); + prop_assert_eq!(return_value, None); + } + } +} diff --git a/tooling/noirc_abi/src/printable_type.rs b/tooling/noirc_abi/src/printable_type.rs new file mode 100644 index 00000000000..a81eb0ce8f6 --- /dev/null +++ b/tooling/noirc_abi/src/printable_type.rs @@ -0,0 +1,78 @@ +use std::collections::BTreeMap; + +use acvm::acir::AcirField; +use iter_extended::vecmap; + +use noirc_printable_type::{PrintableType, PrintableValue}; + +use crate::decode_string_value; + +/// Assumes that `field_iterator` contains enough field elements in order to decode the [PrintableType] +pub fn decode_value( + field_iterator: &mut impl Iterator, + typ: &PrintableType, +) -> PrintableValue { + match typ { + PrintableType::Field + | PrintableType::SignedInteger { .. } + | PrintableType::UnsignedInteger { .. } + | PrintableType::Boolean => { + let field_element = field_iterator.next().unwrap(); + + PrintableValue::Field(field_element) + } + 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, is_slice: false } + } + 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, 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(); + + PrintableValue::String(decode_string_value(&field_elements)) + } + PrintableType::Struct { fields, .. } => { + let mut struct_map = BTreeMap::new(); + + for (field_key, param_type) in fields { + let field_value = decode_value(field_iterator, param_type); + + struct_map.insert(field_key.to_owned(), field_value); + } + + PrintableValue::Struct(struct_map) + } + 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 + decode_value(field_iterator, env); + func_ref + } + PrintableType::MutableReference { typ } => { + // we decode the reference, but it's not really used for printing + decode_value(field_iterator, typ) + } + PrintableType::Unit => PrintableValue::Field(F::zero()), + } +} diff --git a/tooling/noirc_abi/src/serialization.rs b/tooling/noirc_abi/src/serialization.rs new file mode 100644 index 00000000000..4f91d9b7dfd --- /dev/null +++ b/tooling/noirc_abi/src/serialization.rs @@ -0,0 +1,167 @@ +use crate::{AbiType, AbiValue}; +use iter_extended::vecmap; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +// This module exposes a custom serializer and deserializer for `BTreeMap` +// (representing the fields of a struct) to serialize it as a `Vec`. +// +// This is required as the struct is flattened into an array of field elements so the ordering of the struct's fields +// must be maintained. However, several serialization formats (notably JSON) do not provide strong guarantees about +// the ordering of elements in a map, this creates potential for improper ABI encoding of structs if the fields are +// deserialized into a different order. To prevent this, we store the fields in an array to create an unambiguous ordering. + +#[derive(Serialize, Deserialize)] +struct StructField { + name: String, + #[serde(rename = "type")] + typ: AbiType, +} + +pub(crate) fn serialize_struct_fields( + fields: &[(String, AbiType)], + s: S, +) -> Result +where + S: Serializer, +{ + let fields_vector = + vecmap(fields, |(name, typ)| StructField { name: name.to_owned(), typ: typ.to_owned() }); + + fields_vector.serialize(s) +} + +pub(crate) fn deserialize_struct_fields<'de, D>( + deserializer: D, +) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let fields_vector = Vec::::deserialize(deserializer)?; + 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}; + + #[test] + fn abi_parameter_serialization() { + let serialized_field = "{ + \"name\": \"thing1\", + \"visibility\": \"public\", + \"type\": { + \"kind\": \"field\" + } + }"; + + let expected_field = AbiParameter { + name: "thing1".to_string(), + typ: AbiType::Field, + visibility: AbiVisibility::Public, + }; + let deserialized_field: AbiParameter = serde_json::from_str(serialized_field).unwrap(); + assert_eq!(deserialized_field, expected_field); + + let serialized_array = "{ + \"name\": \"thing2\", + \"visibility\": \"private\", + \"type\": { + \"kind\": \"array\", + \"length\": 2, + \"type\": { + \"kind\": \"integer\", + \"width\": 3, + \"sign\": \"unsigned\" + } + } + }"; + + let expected_array = AbiParameter { + name: "thing2".to_string(), + typ: AbiType::Array { + length: 2, + typ: Box::new(AbiType::Integer { sign: Sign::Unsigned, width: 3 }), + }, + visibility: AbiVisibility::Private, + }; + let deserialized_array: AbiParameter = serde_json::from_str(serialized_array).unwrap(); + assert_eq!(deserialized_array, expected_array); + + let serialized_struct = "{ + \"name\":\"thing3\", + \"type\": { + \"kind\":\"struct\", + \"path\": \"MyStruct\", + \"fields\": [ + { + \"name\": \"field1\", + \"type\": { + \"kind\": \"integer\", + \"sign\": \"unsigned\", + \"width\": 3 + } + }, + { + \"name\":\"field2\", + \"type\": { + \"kind\":\"array\", + \"length\": 2, + \"type\": { + \"kind\":\"field\" + } + } + } + ] + }, + \"visibility\":\"private\" + }"; + + let expected_struct = AbiParameter { + name: "thing3".to_string(), + typ: AbiType::Struct { + path: "MyStruct".to_string(), + fields: vec![ + ("field1".to_string(), AbiType::Integer { sign: Sign::Unsigned, width: 3 }), + ( + "field2".to_string(), + AbiType::Array { length: 2, typ: Box::new(AbiType::Field) }, + ), + ], + }, + visibility: AbiVisibility::Private, + }; + let deserialized_struct: AbiParameter = serde_json::from_str(serialized_struct).unwrap(); + assert_eq!(deserialized_struct, expected_struct); + } +} diff --git a/tooling/noirc_abi_wasm/.eslintignore b/tooling/noirc_abi_wasm/.eslintignore new file mode 100644 index 00000000000..200ae222150 --- /dev/null +++ b/tooling/noirc_abi_wasm/.eslintignore @@ -0,0 +1,2 @@ +node_modules +pkg \ No newline at end of file diff --git a/tooling/noirc_abi_wasm/.eslintrc.js b/tooling/noirc_abi_wasm/.eslintrc.js new file mode 100644 index 00000000000..33335c2a877 --- /dev/null +++ b/tooling/noirc_abi_wasm/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ["../../.eslintrc.js"], +}; diff --git a/tooling/noirc_abi_wasm/.mocharc.json b/tooling/noirc_abi_wasm/.mocharc.json new file mode 100644 index 00000000000..27273835070 --- /dev/null +++ b/tooling/noirc_abi_wasm/.mocharc.json @@ -0,0 +1,5 @@ +{ + "extension": ["ts"], + "spec": "test/node/**/*.test.ts", + "require": "ts-node/register" +} \ No newline at end of file diff --git a/tooling/noirc_abi_wasm/CHANGELOG.md b/tooling/noirc_abi_wasm/CHANGELOG.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tooling/noirc_abi_wasm/Cargo.toml b/tooling/noirc_abi_wasm/Cargo.toml new file mode 100644 index 00000000000..b00d580515e --- /dev/null +++ b/tooling/noirc_abi_wasm/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "noirc_abi_wasm" +description = "An ABI encoder for the Noir language" +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + +[lib] +crate-type = ["cdylib"] + +[dependencies] +acvm = { workspace = true, features = ["bn254"] } +noirc_abi = { workspace = true, features = ["bn254"] } +iter-extended.workspace = true +wasm-bindgen.workspace = true +serde.workspace = true +js-sys.workspace = true +console_error_panic_hook.workspace = true +gloo-utils.workspace = true + + +# This is an unused dependency, we are adding it +# so that we can enable the js feature in getrandom. +getrandom = { workspace = true, features = ["js"] } + +[build-dependencies] +build-data.workspace = true + +[dev-dependencies] +wasm-bindgen-test.workspace = true diff --git a/tooling/noirc_abi_wasm/README.md b/tooling/noirc_abi_wasm/README.md new file mode 100644 index 00000000000..2b0cf9b74d4 --- /dev/null +++ b/tooling/noirc_abi_wasm/README.md @@ -0,0 +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. diff --git a/tooling/noirc_abi_wasm/build.rs b/tooling/noirc_abi_wasm/build.rs new file mode 100644 index 00000000000..7a6eb861de2 --- /dev/null +++ b/tooling/noirc_abi_wasm/build.rs @@ -0,0 +1,13 @@ +const GIT_COMMIT: &&str = &"GIT_COMMIT"; + +fn main() { + // 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(); + build_data::no_debug_rebuilds(); + } + + build_data::set_SOURCE_TIMESTAMP(); + build_data::no_debug_rebuilds(); +} diff --git a/tooling/noirc_abi_wasm/build.sh b/tooling/noirc_abi_wasm/build.sh new file mode 100755 index 00000000000..16fb26e55db --- /dev/null +++ b/tooling/noirc_abi_wasm/build.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +function require_command { + if ! command -v "$1" >/dev/null 2>&1; then + echo "Error: $1 is required but not installed." >&2 + exit 1 + fi +} +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 +} + +require_command jq +require_command cargo +require_command wasm-bindgen +require_command wasm-opt + +self_path=$(dirname "$(readlink -f "$0")") +pname=$(cargo read-manifest | jq -r '.name') + +NODE_DIR=$self_path/nodejs +BROWSER_DIR=$self_path/web + +# 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 + +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 + +# 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/package.json b/tooling/noirc_abi_wasm/package.json new file mode 100644 index 00000000000..0148a9343db --- /dev/null +++ b/tooling/noirc_abi_wasm/package.json @@ -0,0 +1,49 @@ +{ + "name": "@noir-lang/noirc_abi", + "contributors": [ + "The Noir Team " + ], + "version": "1.0.0-beta.1", + "license": "(MIT OR Apache-2.0)", + "homepage": "https://noir-lang.org/", + "repository": { + "url": "https://github.com/noir-lang/noir.git", + "directory": "tooling/noirc_abi_wasm", + "type": "git" + }, + "bugs": { + "url": "https://github.com/noir-lang/noir/issues" + }, + "files": [ + "nodejs", + "web", + "package.json" + ], + "publishConfig": { + "access": "public" + }, + "main": "./nodejs/noirc_abi_wasm.js", + "types": "./web/noirc_abi_wasm.d.ts", + "module": "./web/noirc_abi_wasm.js", + "sideEffects": false, + "scripts": { + "build": "bash ./build.sh", + "test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha", + "test:browser": "web-test-runner", + "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" + }, + "dependencies": { + "@noir-lang/types": "workspace:*" + }, + "devDependencies": { + "@esm-bundle/chai": "^4.3.4-fix.0", + "@web/dev-server-esbuild": "^0.3.6", + "@web/test-runner": "^0.18.1", + "@web/test-runner-playwright": "^0.11.0", + "eslint": "^8.57.0", + "mocha": "^10.2.0" + } +} diff --git a/tooling/noirc_abi_wasm/src/errors.rs b/tooling/noirc_abi_wasm/src/errors.rs new file mode 100644 index 00000000000..14ee2d5fd8e --- /dev/null +++ b/tooling/noirc_abi_wasm/src/errors.rs @@ -0,0 +1,47 @@ +use js_sys::{Error, JsString}; +use noirc_abi::errors::{AbiError, InputParserError}; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen(typescript_custom_section)] +const ABI_ERROR: &'static str = r#" +export type ABIError = Error; +"#; + +/// JsAbiError is a raw js error. +/// It'd be ideal that ABI error was a subclass of Error, but for that we'd need to use JS snippets or a js module. +/// Currently JS snippets don't work with a nodejs target. And a module would be too much for just a custom error type. +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(extends = Error, js_name = "AbiError", typescript_type = "AbiError")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub type JsAbiError; + + #[wasm_bindgen(constructor, js_class = "Error")] + fn constructor(message: JsString) -> JsAbiError; +} + +impl JsAbiError { + /// 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) -> Self { + JsAbiError::constructor(JsString::from(message)) + } +} + +impl From for JsAbiError { + fn from(value: String) -> Self { + JsAbiError::new(value) + } +} + +impl From for JsAbiError { + fn from(value: AbiError) -> Self { + JsAbiError::new(value.to_string()) + } +} + +impl From for JsAbiError { + fn from(value: InputParserError) -> Self { + JsAbiError::new(value.to_string()) + } +} diff --git a/tooling/noirc_abi_wasm/src/js_witness_map.rs b/tooling/noirc_abi_wasm/src/js_witness_map.rs new file mode 100644 index 00000000000..a82621822e4 --- /dev/null +++ b/tooling/noirc_abi_wasm/src/js_witness_map.rs @@ -0,0 +1,108 @@ +//! This can most likely be imported from acvm_js to avoid redefining it here. + +use acvm::{ + acir::native_types::{Witness, WitnessMap}, + AcirField, FieldElement, +}; +use js_sys::{JsString, Map}; +use wasm_bindgen::prelude::{wasm_bindgen, JsValue}; + +// WitnessMap +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(extends = Map, js_name = "WitnessMap", typescript_type = "WitnessMap")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub type JsWitnessMap; + + #[wasm_bindgen(constructor, js_class = "Map")] + pub fn new() -> JsWitnessMap; + +} + +impl Default for JsWitnessMap { + 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( + &js_sys::Number::from(key.witness_index()), + &field_element_to_js_string(&value), + ); + } + js_map + } +} + +impl From for WitnessMap { + fn from(js_map: JsWitnessMap) -> Self { + let mut witness_map = WitnessMap::new(); + js_map.for_each(&mut |value, key| { + let witness_index = Witness(key.as_f64().unwrap() as u32); + let witness_value = js_value_to_field_element(value).unwrap(); + witness_map.insert(witness_index, witness_value); + }); + witness_map + } +} + +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")?; + + FieldElement::from_hex(&hex_str) + .ok_or_else(|| format!("Invalid hex string: '{}'", hex_str).into()) +} + +pub(crate) fn field_element_to_js_string(field_element: &FieldElement) -> JsString { + // This currently maps `0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000` + // to the bigint `-1n`. This fails when converting back to a `FieldElement`. + // js_sys::BigInt::from_str(&value.to_hex()).unwrap() + + format!("0x{}", field_element.to_hex()).into() +} + +#[cfg(test)] +mod test { + use wasm_bindgen_test::wasm_bindgen_test as test; + + use std::collections::BTreeMap; + + use acvm::{ + acir::native_types::{Witness, WitnessMap}, + AcirField, FieldElement, + }; + use wasm_bindgen::JsValue; + + use crate::JsWitnessMap; + + #[test] + fn test_witness_map_to_js() { + let witness_map = BTreeMap::from([ + (Witness(1), FieldElement::one()), + (Witness(2), FieldElement::zero()), + (Witness(3), -FieldElement::one()), + ]); + let witness_map = WitnessMap::from(witness_map); + + let js_map = JsWitnessMap::from(witness_map); + + assert_eq!( + js_map.get(&JsValue::from(1)), + JsValue::from_str("0x0000000000000000000000000000000000000000000000000000000000000001") + ); + assert_eq!( + js_map.get(&JsValue::from(2)), + JsValue::from_str("0x0000000000000000000000000000000000000000000000000000000000000000") + ); + assert_eq!( + js_map.get(&JsValue::from(3)), + // Equal to 21888242871839275222246405745257275088548364400416034343698204186575808495616, + // which is field modulus - 1: https://docs.rs/ark-bn254/latest/ark_bn254/ + JsValue::from_str("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000") + ); + } +} diff --git a/tooling/noirc_abi_wasm/src/lib.rs b/tooling/noirc_abi_wasm/src/lib.rs new file mode 100644 index 00000000000..79aecafa742 --- /dev/null +++ b/tooling/noirc_abi_wasm/src/lib.rs @@ -0,0 +1,162 @@ +#![warn(unused_crate_dependencies, unused_extern_crates)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] + +// See Cargo.toml for explanation. +use getrandom as _; + +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, AbiErrorType, MAIN_RETURN_NAME, +}; +use serde::Serialize; +use std::collections::BTreeMap; + +use gloo_utils::format::JsValueSerdeExt; +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; + +mod errors; +mod js_witness_map; + +use errors::JsAbiError; +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, RawAssertionPayload } from "@noir-lang/types"; +export { Field, InputValue, InputMap, Visibility, Sign, AbiType, AbiParameter, Abi, WitnessMap, RawAssertionPayload } from "@noir-lang/types"; +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(extends = js_sys::Object, js_name = "InputMap", typescript_type = "InputMap")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub type JsInputMap; + + #[wasm_bindgen(extends = js_sys::Object, js_name = "InputValue", typescript_type = "InputValue")] + #[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; +} + +#[wasm_bindgen(js_name = abiEncode)] +pub fn abi_encode( + abi: JsAbi, + inputs: JsInputMap, + return_value: Option, +) -> Result { + console_error_panic_hook::set_once(); + let abi: Abi = + JsValueSerdeExt::into_serde(&JsValue::from(abi)).map_err(|err| err.to_string())?; + let inputs: BTreeMap = + JsValueSerdeExt::into_serde(&JsValue::from(inputs)).map_err(|err| err.to_string())?; + let return_value: Option = return_value + .map(|return_value| { + let toml_return_value = JsValueSerdeExt::into_serde(&JsValue::from(return_value)) + .expect("could not decode return value"); + InputValue::try_from_json( + toml_return_value, + &abi.return_type.as_ref().unwrap().abi_type, + MAIN_RETURN_NAME, + ) + }) + .transpose()?; + + let abi_map = abi.to_btree_map(); + let parsed_inputs: BTreeMap = + try_btree_map(abi_map, |(arg_name, abi_type)| { + // Check that toml contains a value for each argument in the ABI. + let value = inputs + .get(&arg_name) + .ok_or_else(|| InputParserError::MissingArgument(arg_name.clone()))?; + InputValue::try_from_json(value.clone(), &abi_type, &arg_name) + .map(|input_value| (arg_name, input_value)) + })?; + + let witness_map = abi.encode(&parsed_inputs, return_value)?; + + Ok(witness_map.into()) +} + +#[wasm_bindgen(js_name = abiDecode)] +pub fn abi_decode(abi: JsAbi, witness_map: JsWitnessMap) -> Result { + console_error_panic_hook::set_once(); + let abi: Abi = + JsValueSerdeExt::into_serde(&JsValue::from(abi)).map_err(|err| err.to_string())?; + + let witness_map = WitnessMap::from(witness_map); + + let (inputs, return_value) = abi.decode(&witness_map)?; + + let abi_types = abi.to_btree_map(); + let inputs_map: BTreeMap = try_btree_map(inputs, |(key, value)| { + JsonTypes::try_from_input_value(&value, &abi_types[&key]).map(|value| (key, value)) + })?; + + let return_value = return_value + .map(|value| JsonTypes::try_from_input_value(&value, &abi.return_type.unwrap().abi_type)) + .transpose()?; + + #[derive(Serialize)] + struct InputsAndReturn { + inputs: BTreeMap, + return_value: Option, + } + + let return_struct = InputsAndReturn { inputs: inputs_map, return_value }; + ::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()) + } + AbiErrorType::String { string } => Ok(JsValue::from_str(&string)), + } +} diff --git a/tooling/noirc_abi_wasm/test/browser/abi_encode.test.ts b/tooling/noirc_abi_wasm/test/browser/abi_encode.test.ts new file mode 100644 index 00000000000..ac18495919c --- /dev/null +++ b/tooling/noirc_abi_wasm/test/browser/abi_encode.test.ts @@ -0,0 +1,22 @@ +import { expect } from '@esm-bundle/chai'; +import initNoirAbi, { abiEncode, abiDecode, WitnessMap, Field } from '@noir-lang/noirc_abi'; +import { DecodedInputs } from '../types'; + +beforeEach(async () => { + await initNoirAbi(); +}); + +it('recovers original inputs when abi encoding and decoding', async () => { + const { abi, inputs } = await import('../shared/abi_encode'); + + const initial_witness: WitnessMap = abiEncode(abi, inputs); + const decoded_inputs: DecodedInputs = abiDecode(abi, initial_witness); + + const foo: Field = inputs.foo as Field; + const bar: Field[] = inputs.bar as Field[]; + expect(BigInt(decoded_inputs.inputs.foo)).to.be.equal(BigInt(foo)); + expect(parseInt(decoded_inputs.inputs.bar[0])).to.be.equal(parseInt(bar[0].toString())); + expect(parseInt(decoded_inputs.inputs.bar[1])).to.be.equal(parseInt(bar[1].toString())); + expect(parseInt(decoded_inputs.inputs.bar[2])).to.be.equal(parseInt(bar[2].toString())); + expect(decoded_inputs.return_value).to.be.null; +}); 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 new file mode 100644 index 00000000000..cc060cff4d6 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/browser/errors.test.ts @@ -0,0 +1,26 @@ +import { expect } from '@esm-bundle/chai'; +import initNoirAbi, { abiEncode } from '@noir-lang/noirc_abi'; + +beforeEach(async () => { + await initNoirAbi(); +}); + +it('errors when an integer input overflows', async () => { + const { abi, inputs } = await import('../shared/uint_overflow'); + + expect(() => abiEncode(abi, inputs)).to.throw( + 'The value passed for parameter `foo` does not match the specified type:\nValue Field(274877906944) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', + ); +}); + +it('errors when passing a field in place of an array', async () => { + const { abi, inputs } = await import('../shared/field_as_array'); + + expect(() => abiEncode(abi, inputs)).to.throw('cannot parse value into Array { length: 2, typ: Field }'); +}); + +it('errors when passing an array in place of a field', async () => { + const { abi, inputs } = await import('../shared/array_as_field'); + + expect(() => abiEncode(abi, inputs)).to.throw('cannot parse value into Field'); +}); diff --git a/tooling/noirc_abi_wasm/test/browser/structs.test.ts b/tooling/noirc_abi_wasm/test/browser/structs.test.ts new file mode 100644 index 00000000000..84352d986ab --- /dev/null +++ b/tooling/noirc_abi_wasm/test/browser/structs.test.ts @@ -0,0 +1,26 @@ +import { expect } from '@esm-bundle/chai'; +import initNoirAbi, { abiEncode, abiDecode, WitnessMap } from '@noir-lang/noirc_abi'; +import { MyNestedStruct, MyStruct } from '../shared/structs'; +import { DecodedInputs } from '../types'; + +beforeEach(async () => { + await initNoirAbi(); +}); + +it('correctly handles struct inputs', async () => { + const { abi, inputs } = await import('../shared/structs'); + + const initial_witness: WitnessMap = abiEncode(abi, inputs); + const decoded_inputs: DecodedInputs = abiDecode(abi, initial_witness); + + const struct_arg: MyStruct = inputs.struct_arg as MyStruct; + const struct_array_arg: MyStruct[] = inputs.struct_array_arg as MyStruct[]; + const nested_struct_arg: MyNestedStruct = inputs.nested_struct_arg as MyNestedStruct; + + expect(BigInt(decoded_inputs.inputs.struct_arg.foo)).to.be.equal(BigInt(struct_arg.foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[0].foo)).to.be.equal(BigInt(struct_array_arg[0].foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[1].foo)).to.be.equal(BigInt(struct_array_arg[1].foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[2].foo)).to.be.equal(BigInt(struct_array_arg[2].foo)); + expect(BigInt(decoded_inputs.inputs.nested_struct_arg.foo.foo)).to.be.equal(BigInt(nested_struct_arg.foo.foo)); + expect(decoded_inputs.return_value).to.be.null; +}); diff --git a/tooling/noirc_abi_wasm/test/node/abi_encode.test.ts b/tooling/noirc_abi_wasm/test/node/abi_encode.test.ts new file mode 100644 index 00000000000..e87618d84da --- /dev/null +++ b/tooling/noirc_abi_wasm/test/node/abi_encode.test.ts @@ -0,0 +1,18 @@ +import { expect } from 'chai'; +import { abiEncode, abiDecode, WitnessMap, Field } from '@noir-lang/noirc_abi'; +import { DecodedInputs } from '../types'; + +it('recovers original inputs when abi encoding and decoding', async () => { + const { abi, inputs } = await import('../shared/abi_encode'); + + const initial_witness: WitnessMap = abiEncode(abi, inputs); + const decoded_inputs: DecodedInputs = abiDecode(abi, initial_witness); + + const foo: Field = inputs.foo as Field; + const bar: Field[] = inputs.bar as Field[]; + expect(BigInt(decoded_inputs.inputs.foo)).to.be.equal(BigInt(foo)); + expect(parseInt(decoded_inputs.inputs.bar[0])).to.be.equal(parseInt(bar[0].toString())); + expect(parseInt(decoded_inputs.inputs.bar[1])).to.be.equal(parseInt(bar[1].toString())); + expect(parseInt(decoded_inputs.inputs.bar[2])).to.be.equal(parseInt(bar[2].toString())); + expect(decoded_inputs.return_value).to.be.null; +}); 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 new file mode 100644 index 00000000000..491fd5a5671 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/node/errors.test.ts @@ -0,0 +1,22 @@ +import { expect } from 'chai'; +import { abiEncode } from '@noir-lang/noirc_abi'; + +it('errors when an integer input overflows', async () => { + const { abi, inputs } = await import('../shared/uint_overflow'); + + expect(() => abiEncode(abi, inputs)).to.throw( + 'The value passed for parameter `foo` does not match the specified type:\nValue Field(274877906944) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', + ); +}); + +it('errors when passing a field in place of an array', async () => { + const { abi, inputs } = await import('../shared/field_as_array'); + + expect(() => abiEncode(abi, inputs)).to.throw('cannot parse value into Array { length: 2, typ: Field }'); +}); + +it('errors when passing an array in place of a field', async () => { + const { abi, inputs } = await import('../shared/array_as_field'); + + expect(() => abiEncode(abi, inputs)).to.throw('cannot parse value into Field'); +}); diff --git a/tooling/noirc_abi_wasm/test/node/structs.test.ts b/tooling/noirc_abi_wasm/test/node/structs.test.ts new file mode 100644 index 00000000000..a7d104b46d3 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/node/structs.test.ts @@ -0,0 +1,22 @@ +import { expect } from 'chai'; +import { abiEncode, abiDecode, WitnessMap } from '@noir-lang/noirc_abi'; +import { MyNestedStruct, MyStruct } from '../shared/structs'; +import { DecodedInputs } from '../types'; + +it('correctly handles struct inputs', async () => { + const { abi, inputs } = await import('../shared/structs'); + + const initial_witness: WitnessMap = abiEncode(abi, inputs); + const decoded_inputs: DecodedInputs = abiDecode(abi, initial_witness); + + const struct_arg: MyStruct = inputs.struct_arg as MyStruct; + const struct_array_arg: MyStruct[] = inputs.struct_array_arg as MyStruct[]; + const nested_struct_arg: MyNestedStruct = inputs.nested_struct_arg as MyNestedStruct; + + expect(BigInt(decoded_inputs.inputs.struct_arg.foo)).to.be.equal(BigInt(struct_arg.foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[0].foo)).to.be.equal(BigInt(struct_array_arg[0].foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[1].foo)).to.be.equal(BigInt(struct_array_arg[1].foo)); + expect(BigInt(decoded_inputs.inputs.struct_array_arg[2].foo)).to.be.equal(BigInt(struct_array_arg[2].foo)); + expect(BigInt(decoded_inputs.inputs.nested_struct_arg.foo.foo)).to.be.equal(BigInt(nested_struct_arg.foo.foo)); + expect(decoded_inputs.return_value).to.be.null; +}); diff --git a/tooling/noirc_abi_wasm/test/shared/abi_encode.ts b/tooling/noirc_abi_wasm/test/shared/abi_encode.ts new file mode 100644 index 00000000000..b789bb05371 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/shared/abi_encode.ts @@ -0,0 +1,19 @@ +import { Abi, InputMap } from '@noir-lang/noirc_abi'; + +export const abi: Abi = { + parameters: [ + { name: 'foo', type: { kind: 'field' }, visibility: 'private' }, + { + name: 'bar', + type: { kind: 'array', length: 3, type: { kind: 'integer', sign: 'signed', width: 32 } }, + visibility: 'private', + }, + ], + return_type: null, + error_types: {}, +}; + +export const inputs: InputMap = { + foo: '1', + bar: ['1', '2', '-1'], +}; diff --git a/tooling/noirc_abi_wasm/test/shared/array_as_field.ts b/tooling/noirc_abi_wasm/test/shared/array_as_field.ts new file mode 100644 index 00000000000..8fecacf79f8 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/shared/array_as_field.ts @@ -0,0 +1,17 @@ +import { Abi, InputMap } from '@noir-lang/noirc_abi'; + +export const abi: Abi = { + parameters: [ + { + name: 'foo', + type: { kind: 'field' }, + visibility: 'private', + }, + ], + return_type: null, + error_types: {}, +}; + +export const inputs: InputMap = { + foo: ['1', '2'], +}; 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..461cedd2694 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/shared/decode_error.ts @@ -0,0 +1,50 @@ +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 FAKE_STRING_SELECTOR = '5'; + +export const SAMPLE_FMT_STRING = 'hello {a}'; +export const SAMPLE_STRING = 'hello world'; + +export const abi: Abi = { + parameters: [ + { + name: 'foo', + type: { kind: 'array', length: 2, type: { kind: 'field' } }, + visibility: 'private', + }, + ], + return_type: null, + 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' } }, + ], + }, + [FAKE_STRING_SELECTOR]: { + error_kind: 'string', + string: SAMPLE_STRING, + }, + }, +}; diff --git a/tooling/noirc_abi_wasm/test/shared/field_as_array.ts b/tooling/noirc_abi_wasm/test/shared/field_as_array.ts new file mode 100644 index 00000000000..3610c51e6db --- /dev/null +++ b/tooling/noirc_abi_wasm/test/shared/field_as_array.ts @@ -0,0 +1,17 @@ +import { Abi, InputMap } from '@noir-lang/noirc_abi'; + +export const abi: Abi = { + parameters: [ + { + name: 'foo', + type: { kind: 'array', length: 2, type: { kind: 'field' } }, + visibility: 'private', + }, + ], + return_type: null, + error_types: {}, +}; + +export const inputs: InputMap = { + foo: '1', +}; diff --git a/tooling/noirc_abi_wasm/test/shared/structs.ts b/tooling/noirc_abi_wasm/test/shared/structs.ts new file mode 100644 index 00000000000..6d098832b3a --- /dev/null +++ b/tooling/noirc_abi_wasm/test/shared/structs.ts @@ -0,0 +1,74 @@ +import { Abi, Field, InputMap } from '@noir-lang/noirc_abi'; + +export type MyStruct = { + foo: Field; +}; + +export type MyNestedStruct = { + foo: MyStruct; +}; + +export const abi: Abi = { + parameters: [ + { + name: 'struct_arg', + type: { kind: 'struct', path: 'MyStruct', fields: [{ name: 'foo', type: { kind: 'field' } }] }, + visibility: 'private', + }, + { + name: 'struct_array_arg', + type: { + kind: 'array', + type: { + kind: 'struct', + path: 'MyStruct', + fields: [{ name: 'foo', type: { kind: 'field' } }], + }, + length: 3, + }, + visibility: 'private', + }, + { + name: 'nested_struct_arg', + type: { + kind: 'struct', + path: 'MyNestedStruct', + fields: [ + { + name: 'foo', + type: { + kind: 'struct', + path: 'MyStruct', + fields: [{ name: 'foo', type: { kind: 'field' } }], + }, + }, + ], + }, + visibility: 'private', + }, + ], + return_type: null, + error_types: {}, +}; + +export const inputs: InputMap = { + struct_arg: { + foo: '1', + }, + struct_array_arg: [ + { + foo: '2', + }, + { + foo: '3', + }, + { + foo: '4', + }, + ], + nested_struct_arg: { + foo: { + foo: '5', + }, + }, +}; diff --git a/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts b/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts new file mode 100644 index 00000000000..b7f1f221b48 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts @@ -0,0 +1,17 @@ +import { Abi, InputMap } from '@noir-lang/noirc_abi'; + +export const abi: Abi = { + parameters: [ + { + name: 'foo', + type: { kind: 'integer', sign: 'unsigned', width: 32 }, + visibility: 'private', + }, + ], + return_type: null, + error_types: {}, +}; + +export const inputs: InputMap = { + foo: `0x${(1n << 38n).toString(16)}`, +}; diff --git a/tooling/noirc_abi_wasm/test/types.ts b/tooling/noirc_abi_wasm/test/types.ts new file mode 100644 index 00000000000..3a72544b8d0 --- /dev/null +++ b/tooling/noirc_abi_wasm/test/types.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type DecodedInputs = { inputs: Record; return_value: any }; diff --git a/tooling/noirc_abi_wasm/tsconfig.json b/tooling/noirc_abi_wasm/tsconfig.json new file mode 100644 index 00000000000..eef2ad84833 --- /dev/null +++ b/tooling/noirc_abi_wasm/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "outDir": "lib", + "target": "ESNext", + "module": "ESNext", + "strict": true, + "experimentalDecorators": true, + "esModuleInterop": true, + "noImplicitAny": true, + "removeComments": false, + "preserveConstEnums": true, + "sourceMap": true, + "resolveJsonModule": true, + "importHelpers": true + } +} \ No newline at end of file diff --git a/tooling/noirc_abi_wasm/web-test-runner.config.mjs b/tooling/noirc_abi_wasm/web-test-runner.config.mjs new file mode 100644 index 00000000000..282c19c1cd2 --- /dev/null +++ b/tooling/noirc_abi_wasm/web-test-runner.config.mjs @@ -0,0 +1,32 @@ +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"; + +// eslint-disable-next-line no-undef +const reporter = process.env.CI ? summaryReporter() : defaultReporter(); + +export default { + browsers: [ + playwrightLauncher({ product: "chromium" }), + // playwrightLauncher({ product: "webkit" }), + // playwrightLauncher({ product: "firefox" }), + ], + plugins: [ + esbuildPlugin({ + ts: true, + }), + ], + files: ["test/browser/**/*.test.ts"], + nodeResolve: true, + testFramework: { + config: { + ui: "bdd", + timeout: 40000, + }, + }, + // eslint-disable-next-line no-undef + rootDir: fileURLToPath(new URL("./../../", import.meta.url)), + reporters: [reporter], +}; diff --git a/tooling/noirc_artifacts/Cargo.toml b/tooling/noirc_artifacts/Cargo.toml new file mode 100644 index 00000000000..13ff68e423a --- /dev/null +++ b/tooling/noirc_artifacts/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "noirc_artifacts" +description = "Definitions of Nargo's build artifacts" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +[lints] +workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +acvm.workspace = true +fm.workspace = true +noirc_abi.workspace = true +noirc_driver.workspace = true +noirc_errors.workspace = true +noirc_printable_type.workspace = true +serde.workspace = true +codespan-reporting.workspace = true + + +[dev-dependencies] +tempfile.workspace = true diff --git a/tooling/noirc_artifacts/src/contract.rs b/tooling/noirc_artifacts/src/contract.rs new file mode 100644 index 00000000000..2b78b647037 --- /dev/null +++ b/tooling/noirc_artifacts/src/contract.rs @@ -0,0 +1,91 @@ +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::ProgramDebugInfo; +use std::collections::{BTreeMap, HashMap}; + +use fm::FileId; + +#[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, + /// The name of the contract. + pub name: String, + /// Each of the contract's functions are compiled into a separate program stored in this `Vec`. + pub functions: 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, +} + +impl From for ContractArtifact { + fn from(contract: CompiledContract) -> Self { + ContractArtifact { + noir_version: contract.noir_version, + name: contract.name, + functions: contract.functions.into_iter().map(ContractFunctionArtifact::from).collect(), + outputs: contract.outputs.into(), + file_map: contract.file_map, + } + } +} + +/// Each function in the contract will be compiled as a separate noir program. +/// +/// A contract function unlike a regular Noir program however can have additional properties. +/// One of these being a function type. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ContractFunctionArtifact { + pub name: String, + + pub is_unconstrained: bool, + + pub custom_attributes: Vec, + + pub abi: Abi, + + #[serde( + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" + )] + pub bytecode: Program, + + #[serde( + serialize_with = "ProgramDebugInfo::serialize_compressed_base64_json", + deserialize_with = "ProgramDebugInfo::deserialize_compressed_base64_json" + )] + pub debug_symbols: ProgramDebugInfo, + + pub brillig_names: Vec, +} + +impl From for ContractFunctionArtifact { + fn from(func: ContractFunction) -> Self { + ContractFunctionArtifact { + name: func.name, + is_unconstrained: func.is_unconstrained, + custom_attributes: func.custom_attributes, + abi: func.abi, + bytecode: func.bytecode, + brillig_names: func.brillig_names, + debug_symbols: ProgramDebugInfo { debug_infos: func.debug }, + } + } +} diff --git a/tooling/noirc_artifacts/src/debug.rs b/tooling/noirc_artifacts/src/debug.rs new file mode 100644 index 00000000000..5c47f1f2652 --- /dev/null +++ b/tooling/noirc_artifacts/src/debug.rs @@ -0,0 +1,274 @@ +use codespan_reporting::files::{Error, Files, SimpleFile}; +use noirc_driver::{CompiledContract, CompiledProgram, DebugFile}; +use noirc_errors::{debug_info::DebugInfo, Location}; +use serde::{Deserialize, Serialize}; +use std::{ + collections::{BTreeMap, BTreeSet}, + ops::Range, +}; + +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 +/// along with a map of file Id to the source code so locations in debug info can be mapped to source code they point to. +#[derive(Debug, Serialize, Deserialize)] +pub struct DebugArtifact { + pub debug_symbols: Vec, + pub file_map: BTreeMap, +} + +impl DebugArtifact { + pub fn new(debug_symbols: Vec, file_manager: &FileManager) -> Self { + let mut file_map = BTreeMap::new(); + + let mut files_with_debug_symbols: BTreeSet = debug_symbols + .iter() + .flat_map(|function_symbols| { + function_symbols + .locations + .values() + .flat_map(|call_stack| call_stack.iter().map(|location| location.file)) + }) + .collect(); + + let files_with_brillig_debug_symbols: BTreeSet = debug_symbols + .iter() + .flat_map(|function_symbols| { + let brillig_location_maps = + function_symbols.brillig_locations.values().flat_map(|brillig_location_map| { + brillig_location_map + .values() + .flat_map(|call_stack| call_stack.iter().map(|location| location.file)) + }); + brillig_location_maps + }) + .collect(); + + files_with_debug_symbols.extend(files_with_brillig_debug_symbols); + + for file_id in files_with_debug_symbols { + let file_path = file_manager.path(file_id).expect("file should exist"); + let file_source = file_manager.fetch_file(file_id).expect("file should exist"); + + file_map.insert( + file_id, + DebugFile { source: file_source.to_string(), path: file_path.to_path_buf() }, + ); + } + + Self { debug_symbols, file_map } + } + + /// Given a location, returns its file's source code + pub fn location_source_code(&self, location: Location) -> Result<&str, Error> { + self.source(location.file) + } + + /// Given a location, returns the index of the line it starts at + pub fn location_line_index(&self, location: Location) -> Result { + let location_start = location.span.start() as usize; + self.line_index(location.file, location_start) + } + + /// Given a location, returns the index of the line it ends at + pub fn location_end_line_index(&self, location: Location) -> Result { + let location_end = location.span.end() as usize; + self.line_index(location.file, location_end) + } + + /// Given a location, returns the line number it starts at + pub fn location_line_number(&self, location: Location) -> Result { + let location_start = location.span.start() as usize; + let line_index = self.line_index(location.file, location_start)?; + self.line_number(location.file, line_index) + } + + /// Given a location, returns the column number it starts at + pub fn location_column_number(&self, location: Location) -> Result { + let location_start = location.span.start() as usize; + let line_index = self.line_index(location.file, location_start)?; + self.column_number(location.file, line_index, location_start) + } + + /// Given a location, returns a Span relative to its line's + /// position in the file. This is useful when processing a file's + /// contents on a per-line-basis. + pub fn location_in_line(&self, location: Location) -> Result, Error> { + let location_start = location.span.start() as usize; + let location_end = location.span.end() as usize; + let line_index = self.line_index(location.file, location_start)?; + let line_span = self.line_range(location.file, line_index)?; + + let line_length = + if line_span.end > line_span.start { line_span.end - (line_span.start + 1) } else { 0 }; + let start_in_line = location_start - line_span.start; + + // The location might continue beyond the line, + // so we need a bounds check + let end_in_line = location_end - line_span.start; + let end_in_line = std::cmp::min(end_in_line, line_length); + + Ok(Range { start: start_in_line, end: end_in_line }) + } + + /// Given a location, returns a Span relative to its last line's + /// position in the file. This is useful when processing a file's + /// contents on a per-line-basis. + pub fn location_in_end_line(&self, location: Location) -> Result, Error> { + let end_line_index = self.location_end_line_index(location)?; + let line_span = self.line_range(location.file, end_line_index)?; + let location_end = location.span.end() as usize; + let end_in_line = location_end - line_span.start; + Ok(Range { start: 0, end: end_in_line }) + } + + /// Given a location, returns the last line index + /// of its file + pub fn last_line_index(&self, location: Location) -> Result { + let source = self.source(location.file)?; + self.line_index(location.file, source.len()) + } +} + +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: program_artifact.debug_symbols.debug_infos, + file_map: program_artifact.file_map, + } + } +} + +impl From for DebugArtifact { + fn from(compiled_artifact: CompiledContract) -> Self { + let all_functions_debug: Vec = compiled_artifact + .functions + .into_iter() + .flat_map(|contract_function| contract_function.debug) + .collect(); + + 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 } + } +} + +impl<'a> Files<'a> for DebugArtifact { + type FileId = FileId; + type Name = PathString; + type Source = &'a str; + + fn name(&self, file_id: Self::FileId) -> Result { + self.file_map.get(&file_id).ok_or(Error::FileMissing).map(|file| file.path.clone().into()) + } + + fn source(&'a self, file_id: Self::FileId) -> Result { + self.file_map.get(&file_id).ok_or(Error::FileMissing).map(|file| file.source.as_ref()) + } + + fn line_index(&self, file_id: Self::FileId, byte_index: usize) -> Result { + self.file_map.get(&file_id).ok_or(Error::FileMissing).and_then(|file| { + SimpleFile::new(PathString::from(file.path.clone()), file.source.clone()) + .line_index((), byte_index) + }) + } + + fn line_range(&self, file_id: Self::FileId, line_index: usize) -> Result, Error> { + self.file_map.get(&file_id).ok_or(Error::FileMissing).and_then(|file| { + SimpleFile::new(PathString::from(file.path.clone()), file.source.clone()) + .line_range((), line_index) + }) + } +} + +#[cfg(test)] +mod tests { + use crate::debug::DebugArtifact; + use acvm::acir::circuit::OpcodeLocation; + use fm::FileManager; + use noirc_errors::{debug_info::DebugInfo, Location, Span}; + use std::collections::BTreeMap; + use std::ops::Range; + use std::path::Path; + use std::path::PathBuf; + use tempfile::{tempdir, TempDir}; + + // Returns the absolute path to the file + fn create_dummy_file(dir: &TempDir, file_name: &Path) -> PathBuf { + let file_path = dir.path().join(file_name); + let _file = std::fs::File::create(&file_path).unwrap(); + file_path + } + + // Tests that location_in_line correctly handles + // locations spanning multiple lines. + // For example, given the snippet: + // ``` + // permute( + // consts::x5_2_config(), + // state); + // ``` + // We want location_in_line to return the range + // containing `permute(` + #[test] + fn location_in_line_stops_at_end_of_line() { + let source_code = r##"pub fn main(mut state: [Field; 2]) -> [Field; 2] { + state = permute( + consts::x5_2_config(), + state); + + state +}"##; + + let dir = tempdir().unwrap(); + let file_name = Path::new("main.nr"); + create_dummy_file(&dir, file_name); + + let mut fm = FileManager::new(dir.path()); + let file_id = fm.add_file_with_source(file_name, source_code.to_string()).unwrap(); + + // Location of + // ``` + // permute( + // consts::x5_2_config(), + // state) + // ``` + let loc = Location::new(Span::inclusive(63, 116), file_id); + + // We don't care about opcodes in this context, + // we just use a dummy to construct debug_symbols + 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(), + 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"); + assert_eq!(location_in_line, Range { start: 12, end: 20 }); + } +} diff --git a/tooling/noirc_artifacts/src/debug_vars.rs b/tooling/noirc_artifacts/src/debug_vars.rs new file mode 100644 index 00000000000..8efeeebb3aa --- /dev/null +++ b/tooling/noirc_artifacts/src/debug_vars.rs @@ -0,0 +1,169 @@ +use acvm::AcirField; +use noirc_abi::decode_printable_value; +use noirc_errors::debug_info::{ + DebugFnId, DebugFunction, DebugInfo, DebugTypeId, DebugVarId, DebugVariable, +}; +use noirc_printable_type::{PrintableType, PrintableValue}; +use std::collections::HashMap; + +#[derive(Debug, Default, Clone)] +pub struct DebugVars { + variables: HashMap, + functions: HashMap, + types: HashMap, + frames: Vec<(DebugFnId, HashMap>)>, +} + +pub struct StackFrame<'a, F> { + pub function_name: &'a str, + pub function_params: Vec<&'a str>, + pub variables: Vec<(&'a str, &'a PrintableValue, &'a PrintableType)>, +} + +impl DebugVars { + 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)) + } + + 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)) + }) + } + + fn build_stack_frame<'a>( + &'a self, + fn_id: &DebugFnId, + frame: &'a HashMap>, + ) -> StackFrame<'a, F> { + 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: &[F]) { + let type_id = &self.variables.get(&var_id).unwrap().debug_type_id; + let ptype = self.types.get(type_id).unwrap(); + + self.frames + .last_mut() + .expect("unexpected empty stack frames") + .1 + .insert(var_id, decode_printable_value(&mut values.iter().copied(), ptype)); + } + + pub fn assign_field(&mut self, var_id: DebugVarId, indexes: Vec, values: &[F]) { + 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 + .variables + .get(&var_id) + .unwrap_or_else(|| panic!("variable {var_id:?} not found")) + .debug_type_id; + let mut cursor_type = self + .types + .get(cursor_type_id) + .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_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_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), + PrintableType::Struct { name: _name, fields }, + ) => { + if *index as usize >= fields.len() { + panic!("unexpected field index past struct field length") + } + let (key, typ) = fields.get(*index as usize).unwrap(); + (field_map.get_mut(key).unwrap(), typ) + } + ( + 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_elements.len() { + panic!("type/array length mismatch") + } + let typ = types.get(*index as usize).unwrap(); + (array_elements.get_mut(*index as usize).unwrap(), typ) + } + _ => { + panic!("unexpected assign field of {cursor_type:?} type"); + } + }; + } + *cursor = decode_printable_value(&mut values.iter().copied(), cursor_type); + } + + pub fn assign_deref(&mut self, _var_id: DebugVarId, _values: &[F]) { + unimplemented![] + } + + pub fn get_type(&self, var_id: DebugVarId) -> Option<&PrintableType> { + self.variables.get(&var_id).and_then(|debug_var| self.types.get(&debug_var.debug_type_id)) + } + + pub fn drop_var(&mut self, var_id: DebugVarId) { + 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/noirc_artifacts/src/lib.rs b/tooling/noirc_artifacts/src/lib.rs new file mode 100644 index 00000000000..77873ed9409 --- /dev/null +++ b/tooling/noirc_artifacts/src/lib.rs @@ -0,0 +1,15 @@ +#![forbid(unsafe_code)] +#![warn(unused_crate_dependencies, unused_extern_crates)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] + +//! This module defines the structure of Nargo's different compilation artifacts. +//! +//! These artifacts are intended to remain independent of any applications being built on top of Noir. +//! Should any projects require/desire a different artifact format, it's expected that they will write a transformer +//! to generate them using these artifacts as a starting point. + +pub mod contract; +pub mod debug; +mod debug_vars; +pub mod program; diff --git a/tooling/noirc_artifacts/src/program.rs b/tooling/noirc_artifacts/src/program.rs new file mode 100644 index 00000000000..ffffc6345d5 --- /dev/null +++ b/tooling/noirc_artifacts/src/program.rs @@ -0,0 +1,73 @@ +use std::collections::BTreeMap; + +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::ProgramDebugInfo; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub struct ProgramArtifact { + pub noir_version: String, + + /// Hash of the [`Program`][noirc_frontend::monomorphization::ast::Program] from which this [`ProgramArtifact`] + /// was compiled. + /// + /// Used to short-circuit compilation in the case of the source code not changing since the last compilation. + pub hash: u64, + + pub abi: Abi, + + #[serde( + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" + )] + pub bytecode: Program, + + #[serde( + serialize_with = "ProgramDebugInfo::serialize_compressed_base64_json", + deserialize_with = "ProgramDebugInfo::deserialize_compressed_base64_json" + )] + 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, + /// Names of the unconstrained functions in the program. + pub brillig_names: Vec, +} + +impl From for ProgramArtifact { + fn from(compiled_program: CompiledProgram) -> Self { + ProgramArtifact { + 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, + brillig_names: compiled_program.brillig_names, + } + } +} + +impl From for CompiledProgram { + fn from(program: ProgramArtifact) -> Self { + CompiledProgram { + hash: program.hash, + abi: program.abi, + noir_version: program.noir_version, + program: program.bytecode, + debug: program.debug_symbols.debug_infos, + file_map: program.file_map, + warnings: vec![], + names: program.names, + brillig_names: program.brillig_names, + } + } +} diff --git a/tooling/profiler/Cargo.toml b/tooling/profiler/Cargo.toml new file mode 100644 index 00000000000..798a21ea0d6 --- /dev/null +++ b/tooling/profiler/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "noir_profiler" +description = "Profiler for noir circuits" +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true +repository.workspace = true + +[lints] +workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[[bin]] +name = "noir-profiler" +path = "src/main.rs" + +[dependencies] +bn254_blackbox_solver.workspace = true +color-eyre.workspace = true +clap.workspace = true +fxhash.workspace = true +noirc_artifacts.workspace = true +const_format.workspace = true +serde.workspace = true +serde_json.workspace = true +fm.workspace = true +inferno = "0.11.19" +im.workspace = true +acir.workspace = true +nargo.workspace = true +noirc_errors.workspace = true +noirc_abi.workspace = true +noirc_evaluator.workspace = true + +# Logs +tracing-subscriber.workspace = true +tracing-appender = "0.2.3" + +[dev-dependencies] +noirc_abi.workspace = true +noirc_driver.workspace = true +tempfile.workspace = true + diff --git a/tooling/profiler/src/cli/execution_flamegraph_cmd.rs b/tooling/profiler/src/cli/execution_flamegraph_cmd.rs new file mode 100644 index 00000000000..dbb2a2c38bc --- /dev/null +++ b/tooling/profiler/src/cli/execution_flamegraph_cmd.rs @@ -0,0 +1,106 @@ +use std::path::{Path, PathBuf}; + +use acir::circuit::OpcodeLocation; +use clap::Args; +use color_eyre::eyre::{self, Context}; +use nargo::foreign_calls::DefaultForeignCallBuilder; +use nargo::PrintOutput; + +use crate::flamegraph::{BrilligExecutionSample, FlamegraphGenerator, InfernoFlamegraphGenerator}; +use crate::fs::{read_inputs_from_file, read_program_from_file}; +use crate::opcode_formatter::format_brillig_opcode; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use noirc_abi::input_parser::Format; +use noirc_artifacts::debug::DebugArtifact; + +#[derive(Debug, Clone, Args)] +pub(crate) struct ExecutionFlamegraphCommand { + /// The path to the artifact JSON file + #[clap(long, short)] + artifact_path: PathBuf, + + /// The path to the Prover.toml file + #[clap(long, short)] + prover_toml_path: PathBuf, + + /// The output folder for the flamegraph svg files + #[clap(long, short)] + output: PathBuf, + + /// Use pedantic ACVM solving, i.e. double-check some black-box function + /// assumptions when solving. + /// This is disabled by default. + #[clap(long, default_value = "false")] + pedantic_solving: bool, +} + +pub(crate) fn run(args: ExecutionFlamegraphCommand) -> eyre::Result<()> { + run_with_generator( + &args.artifact_path, + &args.prover_toml_path, + &InfernoFlamegraphGenerator { count_name: "samples".to_string() }, + &args.output, + args.pedantic_solving, + ) +} + +fn run_with_generator( + artifact_path: &Path, + prover_toml_path: &Path, + flamegraph_generator: &impl FlamegraphGenerator, + output_path: &Path, + pedantic_solving: bool, +) -> eyre::Result<()> { + let program = + read_program_from_file(artifact_path).context("Error reading program from file")?; + + let (inputs_map, _) = read_inputs_from_file(prover_toml_path, Format::Toml, &program.abi)?; + + let initial_witness = program.abi.encode(&inputs_map, None)?; + + println!("Executing"); + let (_, mut profiling_samples) = nargo::ops::execute_program_with_profiling( + &program.bytecode, + initial_witness, + &Bn254BlackBoxSolver(pedantic_solving), + &mut DefaultForeignCallBuilder::default().with_output(PrintOutput::Stdout).build(), + )?; + println!("Executed"); + + println!("Collecting {} samples", profiling_samples.len()); + + let profiling_samples: Vec = profiling_samples + .iter_mut() + .map(|sample| { + let call_stack = std::mem::take(&mut sample.call_stack); + let brillig_function_id = std::mem::take(&mut sample.brillig_function_id); + let last_entry = call_stack.last(); + let opcode = brillig_function_id + .and_then(|id| program.bytecode.unconstrained_functions.get(id.0 as usize)) + .and_then(|func| { + if let Some(OpcodeLocation::Brillig { brillig_index, .. }) = last_entry { + func.bytecode.get(*brillig_index) + } else { + None + } + }) + .map(format_brillig_opcode); + BrilligExecutionSample { opcode, call_stack, brillig_function_id } + }) + .collect(); + + let debug_artifact: DebugArtifact = program.into(); + + println!("Generating flamegraph with {} samples", profiling_samples.len()); + + flamegraph_generator.generate_flamegraph( + profiling_samples, + &debug_artifact.debug_symbols[0], + &debug_artifact, + artifact_path.to_str().unwrap(), + "main", + &Path::new(&output_path).join(Path::new(&format!("{}.svg", "main"))), + )?; + + Ok(()) +} diff --git a/tooling/profiler/src/cli/gates_flamegraph_cmd.rs b/tooling/profiler/src/cli/gates_flamegraph_cmd.rs new file mode 100644 index 00000000000..e68a8cd5bd2 --- /dev/null +++ b/tooling/profiler/src/cli/gates_flamegraph_cmd.rs @@ -0,0 +1,216 @@ +use std::path::{Path, PathBuf}; + +use acir::circuit::OpcodeLocation; +use clap::Args; +use color_eyre::eyre::{self, Context}; + +use noirc_artifacts::debug::DebugArtifact; + +use crate::flamegraph::{CompilationSample, FlamegraphGenerator, InfernoFlamegraphGenerator}; +use crate::fs::read_program_from_file; +use crate::gates_provider::{BackendGatesProvider, GatesProvider}; +use crate::opcode_formatter::format_acir_opcode; + +#[derive(Debug, Clone, Args)] +pub(crate) struct GatesFlamegraphCommand { + /// The path to the artifact JSON file + #[clap(long, short)] + artifact_path: String, + + /// Path to the noir backend binary + #[clap(long, short)] + backend_path: String, + + /// Command to get a gates report from the backend. Defaults to "gates" + #[clap(long, short = 'g', default_value = "gates")] + backend_gates_command: String, + + #[arg(trailing_var_arg = true, allow_hyphen_values = true)] + backend_extra_args: Vec, + + /// The output folder for the flamegraph svg files + #[clap(long, short)] + output: String, + + /// The output name for the flamegraph svg files + #[clap(long, short = 'f')] + output_filename: Option, +} + +pub(crate) fn run(args: GatesFlamegraphCommand) -> eyre::Result<()> { + run_with_provider( + &PathBuf::from(args.artifact_path), + &BackendGatesProvider { + backend_path: PathBuf::from(args.backend_path), + gates_command: args.backend_gates_command, + extra_args: args.backend_extra_args, + }, + &InfernoFlamegraphGenerator { count_name: "gates".to_string() }, + &PathBuf::from(args.output), + args.output_filename, + ) +} + +fn run_with_provider( + artifact_path: &Path, + gates_provider: &Provider, + flamegraph_generator: &Generator, + output_path: &Path, + output_filename: Option, +) -> eyre::Result<()> { + let mut program = + read_program_from_file(artifact_path).context("Error reading program from file")?; + + let backend_gates_response = + gates_provider.get_gates(artifact_path).context("Error querying backend for gates")?; + + let function_names = program.names.clone(); + + let bytecode = std::mem::take(&mut program.bytecode); + + let debug_artifact: DebugArtifact = program.into(); + + for (func_idx, ((func_gates, func_name), bytecode)) in backend_gates_response + .functions + .into_iter() + .zip(function_names) + .zip(bytecode.functions) + .enumerate() + { + println!( + "Opcode count: {}, Total gates by opcodes: {}, Circuit size: {}", + func_gates.acir_opcodes, + func_gates.gates_per_opcode.iter().sum::(), + func_gates.circuit_size + ); + + let samples = func_gates + .gates_per_opcode + .into_iter() + .zip(bytecode.opcodes) + .enumerate() + .map(|(index, (gates, opcode))| CompilationSample { + opcode: Some(format_acir_opcode(&opcode)), + call_stack: vec![OpcodeLocation::Acir(index)], + count: gates, + brillig_function_id: None, + }) + .collect(); + + let output_filename = if let Some(output_filename) = &output_filename { + format!("{}::{}::gates.svg", output_filename, func_name) + } else { + format!("{}::gates.svg", func_name) + }; + flamegraph_generator.generate_flamegraph( + samples, + &debug_artifact.debug_symbols[func_idx], + &debug_artifact, + artifact_path.to_str().unwrap(), + &func_name, + &Path::new(&output_path).join(Path::new(&output_filename)), + )?; + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use acir::circuit::{Circuit, Program}; + use color_eyre::eyre::{self}; + use fm::codespan_files::Files; + use noirc_artifacts::program::ProgramArtifact; + use noirc_errors::debug_info::{DebugInfo, ProgramDebugInfo}; + use std::{ + collections::{BTreeMap, HashMap}, + path::{Path, PathBuf}, + }; + + use crate::{ + flamegraph::Sample, + gates_provider::{BackendGatesReport, BackendGatesResponse, GatesProvider}, + }; + + struct TestGateProvider { + mock_responses: HashMap, + } + + impl GatesProvider for TestGateProvider { + fn get_gates(&self, artifact_path: &Path) -> eyre::Result { + let response = self + .mock_responses + .get(artifact_path) + .expect("should have a mock response for the artifact path"); + + Ok(response.clone()) + } + } + + #[derive(Default)] + struct TestFlamegraphGenerator {} + + impl super::FlamegraphGenerator for TestFlamegraphGenerator { + fn generate_flamegraph<'files, S: Sample>( + &self, + _samples: Vec, + _debug_symbols: &DebugInfo, + _files: &'files impl Files<'files, FileId = fm::FileId>, + _artifact_name: &str, + _function_name: &str, + output_path: &Path, + ) -> eyre::Result<()> { + let output_file = std::fs::File::create(output_path).unwrap(); + std::io::Write::write_all(&mut std::io::BufWriter::new(output_file), b"success") + .unwrap(); + + Ok(()) + } + } + + #[test] + fn smoke_test() { + let temp_dir = tempfile::tempdir().unwrap(); + + let artifact_path = temp_dir.path().join("test.json"); + + let artifact = ProgramArtifact { + noir_version: "0.0.0".to_string(), + hash: 27, + abi: noirc_abi::Abi::default(), + bytecode: Program { functions: vec![Circuit::default()], ..Program::default() }, + debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] }, + file_map: BTreeMap::default(), + names: vec!["main".to_string()], + brillig_names: Vec::new(), + }; + + // Write the artifact to a file + let artifact_file = std::fs::File::create(&artifact_path).unwrap(); + serde_json::to_writer(artifact_file, &artifact).unwrap(); + + let mock_gates_response = BackendGatesResponse { + functions: vec![ + (BackendGatesReport { acir_opcodes: 0, gates_per_opcode: vec![], circuit_size: 0 }), + ], + }; + + let provider = TestGateProvider { + mock_responses: HashMap::from([(artifact_path.clone(), mock_gates_response)]), + }; + let flamegraph_generator = TestFlamegraphGenerator::default(); + + super::run_with_provider( + &artifact_path, + &provider, + &flamegraph_generator, + temp_dir.path(), + Some(String::from("test_filename")), + ) + .expect("should run without errors"); + + // Check that the output file was written to + let output_file = temp_dir.path().join("test_filename::main::gates.svg"); + assert!(output_file.exists()); + } +} diff --git a/tooling/profiler/src/cli/mod.rs b/tooling/profiler/src/cli/mod.rs new file mode 100644 index 00000000000..80c6bceb3ce --- /dev/null +++ b/tooling/profiler/src/cli/mod.rs @@ -0,0 +1,36 @@ +use clap::{Parser, Subcommand}; +use color_eyre::eyre; +use const_format::formatcp; + +mod execution_flamegraph_cmd; +mod gates_flamegraph_cmd; +mod opcodes_flamegraph_cmd; + +const PROFILER_VERSION: &str = env!("CARGO_PKG_VERSION"); + +static VERSION_STRING: &str = formatcp!("version = {}\n", PROFILER_VERSION,); + +#[derive(Parser, Debug)] +#[command(name="Noir profiler", author, version=VERSION_STRING, about, long_about = None)] +struct ProfilerCli { + #[command(subcommand)] + command: ProfilerCommand, +} + +#[non_exhaustive] +#[derive(Subcommand, Clone, Debug)] +enum ProfilerCommand { + Gates(gates_flamegraph_cmd::GatesFlamegraphCommand), + Opcodes(opcodes_flamegraph_cmd::OpcodesFlamegraphCommand), + ExecutionOpcodes(execution_flamegraph_cmd::ExecutionFlamegraphCommand), +} + +pub(crate) fn start_cli() -> eyre::Result<()> { + let ProfilerCli { command } = ProfilerCli::parse(); + + match command { + ProfilerCommand::Gates(args) => gates_flamegraph_cmd::run(args), + ProfilerCommand::Opcodes(args) => opcodes_flamegraph_cmd::run(args), + ProfilerCommand::ExecutionOpcodes(args) => execution_flamegraph_cmd::run(args), + } +} diff --git a/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs b/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs new file mode 100644 index 00000000000..4e271c9f838 --- /dev/null +++ b/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs @@ -0,0 +1,254 @@ +use std::path::{Path, PathBuf}; + +use acir::circuit::brillig::BrilligFunctionId; +use acir::circuit::{Circuit, Opcode, OpcodeLocation}; +use clap::Args; +use color_eyre::eyre::{self, Context}; + +use noirc_artifacts::debug::DebugArtifact; + +use crate::flamegraph::{CompilationSample, FlamegraphGenerator, InfernoFlamegraphGenerator}; +use crate::fs::read_program_from_file; +use crate::opcode_formatter::{format_acir_opcode, format_brillig_opcode}; + +#[derive(Debug, Clone, Args)] +pub(crate) struct OpcodesFlamegraphCommand { + /// The path to the artifact JSON file + #[clap(long, short)] + artifact_path: String, + + /// The output folder for the flamegraph svg files + #[clap(long, short)] + output: String, + + /// Whether to skip brillig functions + #[clap(long, short, action)] + skip_brillig: bool, +} + +pub(crate) fn run(args: OpcodesFlamegraphCommand) -> eyre::Result<()> { + run_with_generator( + &PathBuf::from(args.artifact_path), + &InfernoFlamegraphGenerator { count_name: "opcodes".to_string() }, + &PathBuf::from(args.output), + args.skip_brillig, + ) +} + +fn run_with_generator( + artifact_path: &Path, + flamegraph_generator: &Generator, + output_path: &Path, + skip_brillig: bool, +) -> eyre::Result<()> { + let mut program = + read_program_from_file(artifact_path).context("Error reading program from file")?; + + let function_names = program.names.clone(); + + let bytecode = std::mem::take(&mut program.bytecode); + + let debug_artifact: DebugArtifact = program.into(); + + for (func_idx, (func_name, bytecode)) in + function_names.into_iter().zip(bytecode.functions.iter()).enumerate() + { + println!("Opcode count for {}: {}", func_name, bytecode.opcodes.len()); + + let samples = bytecode + .opcodes + .iter() + .enumerate() + .map(|(index, opcode)| CompilationSample { + opcode: Some(format_acir_opcode(opcode)), + call_stack: vec![OpcodeLocation::Acir(index)], + count: 1, + brillig_function_id: None, + }) + .collect(); + + flamegraph_generator.generate_flamegraph( + samples, + &debug_artifact.debug_symbols[func_idx], + &debug_artifact, + artifact_path.to_str().unwrap(), + &func_name, + &Path::new(&output_path).join(Path::new(&format!("{}_acir_opcodes.svg", &func_name))), + )?; + } + + if !skip_brillig { + for (brillig_fn_index, brillig_bytecode) in + bytecode.unconstrained_functions.into_iter().enumerate() + { + let acir_location = locate_brillig_call(brillig_fn_index, &bytecode.functions); + let Some((acir_fn_index, acir_opcode_index)) = acir_location else { + continue; + }; + + println!( + "Opcode count for brillig_{}: {}", + brillig_fn_index, + brillig_bytecode.bytecode.len() + ); + + let samples = brillig_bytecode + .bytecode + .into_iter() + .enumerate() + .map(|(brillig_index, opcode)| CompilationSample { + opcode: Some(format_brillig_opcode(&opcode)), + call_stack: vec![OpcodeLocation::Brillig { + acir_index: acir_opcode_index, + brillig_index, + }], + count: 1, + brillig_function_id: Some(BrilligFunctionId(brillig_fn_index as u32)), + }) + .collect(); + + flamegraph_generator.generate_flamegraph( + samples, + &debug_artifact.debug_symbols[acir_fn_index], + &debug_artifact, + artifact_path.to_str().unwrap(), + &format!("brillig_{}", brillig_fn_index), + &Path::new(&output_path) + .join(Path::new(&format!("{}_brillig_opcodes.svg", &brillig_fn_index))), + )?; + } + } + + Ok(()) +} + +fn locate_brillig_call( + brillig_fn_index: usize, + acir_functions: &[Circuit], +) -> Option<(usize, usize)> { + for (acir_fn_index, acir_fn) in acir_functions.iter().enumerate() { + for (acir_opcode_index, acir_opcode) in acir_fn.opcodes.iter().enumerate() { + match acir_opcode { + Opcode::BrilligCall { id, .. } if id.as_usize() == brillig_fn_index => { + return Some((acir_fn_index, acir_opcode_index)) + } + _ => {} + } + } + } + None +} + +#[cfg(test)] +mod tests { + use acir::{ + circuit::{ + brillig::{BrilligBytecode, BrilligFunctionId}, + Circuit, Opcode, Program, + }, + FieldElement, + }; + use color_eyre::eyre::{self}; + use fm::codespan_files::Files; + use noirc_artifacts::program::ProgramArtifact; + use noirc_errors::debug_info::{DebugInfo, ProgramDebugInfo}; + use std::{collections::BTreeMap, path::Path}; + + use crate::flamegraph::Sample; + + #[derive(Default)] + struct TestFlamegraphGenerator {} + + impl super::FlamegraphGenerator for TestFlamegraphGenerator { + fn generate_flamegraph<'files, S: Sample>( + &self, + _samples: Vec, + _debug_symbols: &DebugInfo, + _files: &'files impl Files<'files, FileId = fm::FileId>, + _artifact_name: &str, + _function_name: &str, + output_path: &Path, + ) -> eyre::Result<()> { + let output_file = std::fs::File::create(output_path).unwrap(); + std::io::Write::write_all(&mut std::io::BufWriter::new(output_file), b"success") + .unwrap(); + + Ok(()) + } + } + + #[test] + fn smoke_test() { + let temp_dir = tempfile::tempdir().unwrap(); + + let artifact_path = temp_dir.path().join("test.json"); + + let artifact = ProgramArtifact { + noir_version: "0.0.0".to_string(), + hash: 27, + abi: noirc_abi::Abi::default(), + bytecode: Program { functions: vec![Circuit::default()], ..Program::default() }, + debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] }, + file_map: BTreeMap::default(), + names: vec!["main".to_string()], + brillig_names: Vec::new(), + }; + + // Write the artifact to a file + let artifact_file = std::fs::File::create(&artifact_path).unwrap(); + serde_json::to_writer(artifact_file, &artifact).unwrap(); + + let flamegraph_generator = TestFlamegraphGenerator::default(); + + super::run_with_generator(&artifact_path, &flamegraph_generator, temp_dir.path(), true) + .expect("should run without errors"); + + // Check that the output file was written to + let output_file = temp_dir.path().join("main_acir_opcodes.svg"); + assert!(output_file.exists()); + } + + #[test] + fn brillig_test() { + let temp_dir = tempfile::tempdir().unwrap(); + + let artifact_path = temp_dir.path().join("test.json"); + + let acir: Vec> = vec![Opcode::BrilligCall { + id: BrilligFunctionId(0), + inputs: vec![], + outputs: vec![], + predicate: None, + }]; + + let artifact = ProgramArtifact { + noir_version: "0.0.0".to_string(), + hash: 27, + abi: noirc_abi::Abi::default(), + bytecode: Program { + functions: vec![Circuit { opcodes: acir, ..Circuit::default() }], + unconstrained_functions: vec![BrilligBytecode::default()], + }, + debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] }, + file_map: BTreeMap::default(), + names: vec!["main".to_string()], + brillig_names: vec!["main".to_string()], + }; + + // Write the artifact to a file + let artifact_file = std::fs::File::create(&artifact_path).unwrap(); + serde_json::to_writer(artifact_file, &artifact).unwrap(); + + let flamegraph_generator = TestFlamegraphGenerator::default(); + + super::run_with_generator(&artifact_path, &flamegraph_generator, temp_dir.path(), false) + .expect("should run without errors"); + + // Check that the output files ware written to + let output_file = temp_dir.path().join("main_acir_opcodes.svg"); + assert!(output_file.exists()); + + let output_file = temp_dir.path().join("0_brillig_opcodes.svg"); + assert!(output_file.exists()); + } +} diff --git a/tooling/profiler/src/flamegraph.rs b/tooling/profiler/src/flamegraph.rs new file mode 100644 index 00000000000..38966902314 --- /dev/null +++ b/tooling/profiler/src/flamegraph.rs @@ -0,0 +1,431 @@ +use std::path::Path; +use std::{collections::BTreeMap, io::BufWriter}; + +use acir::circuit::brillig::BrilligFunctionId; +use acir::circuit::OpcodeLocation; +use color_eyre::eyre::{self}; +use fm::codespan_files::Files; +use fxhash::FxHashMap as HashMap; +use inferno::flamegraph::{from_lines, Options, TextTruncateDirection}; +use noirc_errors::debug_info::DebugInfo; +use noirc_errors::reporter::line_and_column_from_span; +use noirc_errors::Location; +use noirc_evaluator::brillig::ProcedureId; + +pub(crate) trait Sample { + fn count(&self) -> usize; + + fn brillig_function_id(&self) -> Option; + + fn call_stack(&self) -> &[OpcodeLocation]; + + fn opcode(self) -> Option; +} + +#[derive(Debug)] +pub(crate) struct CompilationSample { + pub(crate) opcode: Option, + pub(crate) call_stack: Vec, + pub(crate) count: usize, + pub(crate) brillig_function_id: Option, +} + +impl Sample for CompilationSample { + fn count(&self) -> usize { + self.count + } + + fn brillig_function_id(&self) -> Option { + self.brillig_function_id + } + + fn call_stack(&self) -> &[OpcodeLocation] { + &self.call_stack + } + + fn opcode(self) -> Option { + self.opcode + } +} + +pub(crate) struct BrilligExecutionSample { + pub(crate) opcode: Option, + pub(crate) call_stack: Vec, + pub(crate) brillig_function_id: Option, +} + +impl Sample for BrilligExecutionSample { + fn count(&self) -> usize { + 1 + } + + fn brillig_function_id(&self) -> Option { + self.brillig_function_id + } + + fn call_stack(&self) -> &[OpcodeLocation] { + &self.call_stack + } + + fn opcode(self) -> Option { + self.opcode + } +} + +#[derive(Debug, Default)] +pub(crate) struct FoldedStackItem { + pub(crate) total_samples: usize, + pub(crate) nested_items: BTreeMap, +} + +pub(crate) trait FlamegraphGenerator { + #[allow(clippy::too_many_arguments)] + fn generate_flamegraph<'files, S: Sample>( + &self, + samples: Vec, + debug_symbols: &DebugInfo, + files: &'files impl Files<'files, FileId = fm::FileId>, + artifact_name: &str, + function_name: &str, + output_path: &Path, + ) -> eyre::Result<()>; +} + +pub(crate) struct InfernoFlamegraphGenerator { + pub(crate) count_name: String, +} + +impl FlamegraphGenerator for InfernoFlamegraphGenerator { + fn generate_flamegraph<'files, S: Sample>( + &self, + samples: Vec, + debug_symbols: &DebugInfo, + files: &'files impl Files<'files, FileId = fm::FileId>, + artifact_name: &str, + function_name: &str, + output_path: &Path, + ) -> eyre::Result<()> { + let folded_lines = generate_folded_sorted_lines(samples, debug_symbols, files); + let flamegraph_file = std::fs::File::create(output_path)?; + let flamegraph_writer = BufWriter::new(flamegraph_file); + + let mut options = Options::default(); + options.hash = true; + options.deterministic = true; + options.title = format!("{}-{}", artifact_name, function_name); + options.frame_height = 24; + options.color_diffusion = true; + options.min_width = 0.0; + options.count_name = self.count_name.clone(); + options.text_truncate_direction = TextTruncateDirection::Right; + + from_lines( + &mut options, + folded_lines.iter().map(|as_string| as_string.as_str()), + flamegraph_writer, + )?; + + Ok(()) + } +} + +fn generate_folded_sorted_lines<'files, S: Sample>( + samples: Vec, + debug_symbols: &DebugInfo, + files: &'files impl Files<'files, FileId = fm::FileId>, +) -> Vec { + // Create a nested hashmap with the stack items, folding the gates for all the callsites that are equal + let mut folded_stack_items = BTreeMap::new(); + + let mut resolution_cache: HashMap> = HashMap::default(); + for sample in samples { + let mut location_names = Vec::with_capacity(sample.call_stack().len()); + for opcode_location in sample.call_stack() { + let callsite_labels = resolution_cache + .entry(*opcode_location) + .or_insert_with(|| { + find_callsite_labels( + debug_symbols, + opcode_location, + sample.brillig_function_id(), + files, + ) + }) + .clone(); + + location_names.extend(callsite_labels); + } + + // We move `sample` by calling `sample.opcode()` so we want to fetch the sample count here. + let count = sample.count(); + + if let Some(opcode) = sample.opcode() { + location_names.push(opcode); + } + + add_locations_to_folded_stack_items(&mut folded_stack_items, location_names, count); + } + + to_folded_sorted_lines(&folded_stack_items, Default::default()) +} + +fn find_callsite_labels<'files>( + debug_symbols: &DebugInfo, + opcode_location: &OpcodeLocation, + brillig_function_id: Option, + files: &'files impl Files<'files, FileId = fm::FileId>, +) -> Vec { + let mut procedure_id = None; + let source_locations = debug_symbols.opcode_location(opcode_location).unwrap_or_else(|| { + if let (Some(brillig_function_id), Some(brillig_location)) = + (brillig_function_id, opcode_location.to_brillig_location()) + { + let procedure_locs = debug_symbols.brillig_procedure_locs.get(&brillig_function_id); + if let Some(procedure_locs) = procedure_locs { + for (procedure, range) in procedure_locs.iter() { + if brillig_location.0 >= range.0 && brillig_location.0 <= range.1 { + procedure_id = Some(*procedure); + break; + } + } + } + let brillig_locations = debug_symbols.brillig_locations.get(&brillig_function_id); + if let Some(brillig_locations) = brillig_locations { + brillig_locations.get(&brillig_location).cloned().unwrap_or_default() + } else { + vec![] + } + } else { + vec![] + } + }); + + let mut callsite_labels: Vec<_> = source_locations + .into_iter() + .map(|location| location_to_callsite_label(location, files)) + .collect(); + + if let Some(procedure_id) = procedure_id { + callsite_labels.push(format!("procedure::{}", ProcedureId::from_debug_id(procedure_id))); + } + + callsite_labels +} + +fn location_to_callsite_label<'files>( + location: Location, + files: &'files impl Files<'files, FileId = fm::FileId>, +) -> String { + let filename = + Path::new(&files.name(location.file).expect("should have a file path").to_string()) + .file_name() + .map(|os_str| os_str.to_string_lossy().to_string()) + .unwrap_or("invalid_path".to_string()); + let source = files.source(location.file).expect("should have a file source"); + + let code_slice = source + .as_ref() + .chars() + .skip(location.span.start() as usize) + .take(location.span.end() as usize - location.span.start() as usize) + .collect::(); + + // ";" is used for frame separation, and is not allowed by inferno + // Check code slice for ";" and replace it with 'GREEK QUESTION MARK' (U+037E) + let code_slice = code_slice.replace(';', "\u{037E}"); + + let (line, column) = line_and_column_from_span(source.as_ref(), &location.span); + + format!("{}:{}:{}::{}", filename, line, column, code_slice) +} + +fn add_locations_to_folded_stack_items( + stack_items: &mut BTreeMap, + locations: Vec, + count: usize, +) { + let mut child_map = stack_items; + for (index, location) in locations.iter().enumerate() { + let current_item = child_map.entry(location.clone()).or_default(); + + child_map = &mut current_item.nested_items; + + if index == locations.len() - 1 { + current_item.total_samples += count; + } + } +} + +/// Creates a vector of lines in the format that inferno expects from a nested hashmap of stack items +/// The lines have to be sorted in the following way, exploring the graph in a depth-first manner: +/// main 100 +/// main::foo 0 +/// main::foo::bar 200 +/// main::baz 27 +/// main::baz::qux 800 +fn to_folded_sorted_lines( + folded_stack_items: &BTreeMap, + parent_stacks: im::Vector, +) -> Vec { + let mut result_vector = Vec::with_capacity(folded_stack_items.len()); + + for (location, folded_stack_item) in folded_stack_items.iter() { + if folded_stack_item.total_samples > 0 { + let frame_list: Vec = + parent_stacks.iter().cloned().chain(std::iter::once(location.clone())).collect(); + let line: String = + format!("{} {}", frame_list.join(";"), folded_stack_item.total_samples); + + result_vector.push(line); + }; + + let mut new_parent_stacks = parent_stacks.clone(); + new_parent_stacks.push_back(location.clone()); + let child_lines = + to_folded_sorted_lines(&folded_stack_item.nested_items, new_parent_stacks); + + result_vector.extend(child_lines); + } + + result_vector +} + +#[cfg(test)] +mod tests { + use acir::{ + circuit::{opcodes::BlockId, Opcode as AcirOpcode, OpcodeLocation}, + native_types::Expression, + FieldElement, + }; + use fm::FileManager; + use noirc_errors::{debug_info::DebugInfo, Location, Span}; + use std::{collections::BTreeMap, path::Path}; + + use crate::{flamegraph::CompilationSample, opcode_formatter::format_acir_opcode}; + + use super::generate_folded_sorted_lines; + + fn find_spans_for(source: &str, needle: &str) -> Vec { + let mut spans = Vec::new(); + let mut start = 0; + while let Some(start_idx) = source[start..].find(needle) { + let start_idx = start + start_idx; + let end_idx = start_idx + needle.len(); + spans.push(Span::inclusive(start_idx as u32, end_idx as u32 - 1)); + start = end_idx; + } + spans + } + + #[test] + fn simple_test_case() { + let source_code = r##" + fn main() { + foo(); + bar(); + whatever(); + } + fn foo() { + baz(); + } + fn bar () { + whatever() + } + fn baz () { + whatever() + } + "##; + + let source_file_name = Path::new("main.nr"); + let temp_dir = tempfile::tempdir().unwrap(); + + let mut fm = FileManager::new(temp_dir.path()); + let file_id = fm.add_file_with_source(source_file_name, source_code.to_string()).unwrap(); + + let main_declaration_location = + Location::new(find_spans_for(source_code, "fn main()")[0], file_id); + let main_foo_call_location = + Location::new(find_spans_for(source_code, "foo()")[0], file_id); + let main_bar_call_location = + Location::new(find_spans_for(source_code, "bar()")[0], file_id); + let main_whatever_call_location = + Location::new(find_spans_for(source_code, "whatever()")[0], file_id); + let foo_baz_call_location = Location::new(find_spans_for(source_code, "baz()")[0], file_id); + let bar_whatever_call_location = + Location::new(find_spans_for(source_code, "whatever()")[1], file_id); + let baz_whatever_call_location = + Location::new(find_spans_for(source_code, "whatever()")[2], file_id); + + let mut opcode_locations = BTreeMap::>::new(); + // main::foo::baz::whatever + opcode_locations.insert( + OpcodeLocation::Acir(0), + vec![ + main_declaration_location, + main_foo_call_location, + foo_baz_call_location, + baz_whatever_call_location, + ], + ); + + // main::bar::whatever + opcode_locations.insert( + OpcodeLocation::Acir(1), + vec![main_declaration_location, main_bar_call_location, bar_whatever_call_location], + ); + // main::whatever + opcode_locations.insert( + OpcodeLocation::Acir(2), + vec![main_declaration_location, main_whatever_call_location], + ); + + let debug_info = DebugInfo::new( + opcode_locations, + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + ); + + let samples: Vec = vec![ + CompilationSample { + opcode: Some(format_acir_opcode(&AcirOpcode::AssertZero::( + Expression::default(), + ))), + call_stack: vec![OpcodeLocation::Acir(0)], + count: 10, + brillig_function_id: None, + }, + CompilationSample { + opcode: Some(format_acir_opcode(&AcirOpcode::AssertZero::( + Expression::default(), + ))), + call_stack: vec![OpcodeLocation::Acir(1)], + count: 20, + brillig_function_id: None, + }, + CompilationSample { + opcode: Some(format_acir_opcode(&AcirOpcode::MemoryInit:: { + block_id: BlockId(0), + init: vec![], + block_type: acir::circuit::opcodes::BlockType::Memory, + })), + call_stack: vec![OpcodeLocation::Acir(2)], + count: 30, + brillig_function_id: None, + }, + ]; + + let expected_folded_sorted_lines = vec![ + "main.nr:2:9::fn main();main.nr:3:13::foo();main.nr:8:13::baz();main.nr:14:13::whatever();acir::arithmetic 10".to_string(), + "main.nr:2:9::fn main();main.nr:4:13::bar();main.nr:11:13::whatever();acir::arithmetic 20".to_string(), + "main.nr:2:9::fn main();main.nr:5:13::whatever();acir::memory::init 30".to_string(), + ]; + + let actual_folded_sorted_lines = + generate_folded_sorted_lines(samples, &debug_info, fm.as_file_map()); + + assert_eq!(expected_folded_sorted_lines, actual_folded_sorted_lines); + } +} diff --git a/tooling/profiler/src/fs.rs b/tooling/profiler/src/fs.rs new file mode 100644 index 00000000000..43848504a7f --- /dev/null +++ b/tooling/profiler/src/fs.rs @@ -0,0 +1,42 @@ +use std::{collections::BTreeMap, path::Path}; + +use color_eyre::eyre; +use noirc_abi::{ + input_parser::{Format, InputValue}, + Abi, InputMap, MAIN_RETURN_NAME, +}; +use noirc_artifacts::program::ProgramArtifact; + +pub(crate) fn read_program_from_file>( + circuit_path: P, +) -> eyre::Result { + let file_path = circuit_path.as_ref().with_extension("json"); + + let input_string = std::fs::read(file_path)?; + let program = serde_json::from_slice(&input_string)?; + + Ok(program) +} + +/// Returns the circuit's parameters and its return value, if one exists. +/// # Examples +/// +/// ```ignore +/// let (input_map, return_value): (InputMap, Option) = +/// read_inputs_from_file(path, "Verifier", Format::Toml, &abi)?; +/// ``` +pub(crate) fn read_inputs_from_file( + file_path: &Path, + format: Format, + abi: &Abi, +) -> eyre::Result<(InputMap, Option)> { + if abi.is_empty() { + return Ok((BTreeMap::new(), None)); + } + + let input_string = std::fs::read_to_string(file_path)?; + let mut input_map = format.parse(&input_string, abi)?; + let return_value = input_map.remove(MAIN_RETURN_NAME); + + Ok((input_map, return_value)) +} diff --git a/tooling/profiler/src/gates_provider.rs b/tooling/profiler/src/gates_provider.rs new file mode 100644 index 00000000000..3f07f3e4be6 --- /dev/null +++ b/tooling/profiler/src/gates_provider.rs @@ -0,0 +1,46 @@ +use std::path::{Path, PathBuf}; +use std::process::Command; + +use color_eyre::eyre::{self}; +use serde::{Deserialize, Serialize}; + +pub(crate) trait GatesProvider { + fn get_gates(&self, artifact_path: &Path) -> eyre::Result; +} + +pub(crate) struct BackendGatesProvider { + pub(crate) backend_path: PathBuf, + pub(crate) gates_command: String, + pub(crate) extra_args: Vec, +} + +impl GatesProvider for BackendGatesProvider { + fn get_gates(&self, artifact_path: &Path) -> eyre::Result { + let mut backend_gates_cmd = Command::new(&self.backend_path); + + backend_gates_cmd.arg(self.gates_command.clone()).arg("-b").arg(artifact_path); + + for arg in &self.extra_args { + backend_gates_cmd.arg(arg); + } + + let backend_gates_response = backend_gates_cmd.output()?; + + // Parse the backend gates command stdout as json + let backend_gates_response: BackendGatesResponse = + serde_json::from_slice(&backend_gates_response.stdout)?; + Ok(backend_gates_response) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct BackendGatesReport { + pub(crate) acir_opcodes: usize, + pub(crate) circuit_size: usize, + pub(crate) gates_per_opcode: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct BackendGatesResponse { + pub(crate) functions: Vec, +} diff --git a/tooling/profiler/src/main.rs b/tooling/profiler/src/main.rs new file mode 100644 index 00000000000..b0b42e6ee41 --- /dev/null +++ b/tooling/profiler/src/main.rs @@ -0,0 +1,39 @@ +#![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 flamegraph; +mod fs; +mod gates_provider; +mod opcode_formatter; + +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("PROFILER_LOG_DIR") { + let debug_file = rolling::daily(log_dir, "profiler-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/profiler/src/opcode_formatter.rs b/tooling/profiler/src/opcode_formatter.rs new file mode 100644 index 00000000000..d1081de6c8f --- /dev/null +++ b/tooling/profiler/src/opcode_formatter.rs @@ -0,0 +1,128 @@ +use acir::brillig::{BinaryFieldOp, BinaryIntOp, BlackBoxOp, Opcode as BrilligOpcode}; +use acir::circuit::{opcodes::BlackBoxFuncCall, Opcode as AcirOpcode}; +use acir::AcirField; + +fn format_blackbox_function(call: &BlackBoxFuncCall) -> String { + match call { + BlackBoxFuncCall::AES128Encrypt { .. } => "aes128_encrypt".to_string(), + BlackBoxFuncCall::AND { .. } => "and".to_string(), + BlackBoxFuncCall::XOR { .. } => "xor".to_string(), + BlackBoxFuncCall::RANGE { .. } => "range".to_string(), + BlackBoxFuncCall::Blake2s { .. } => "blake2s".to_string(), + BlackBoxFuncCall::Blake3 { .. } => "blake3".to_string(), + BlackBoxFuncCall::EcdsaSecp256k1 { .. } => "ecdsa_secp256k1".to_string(), + BlackBoxFuncCall::EcdsaSecp256r1 { .. } => "ecdsa_secp256r1".to_string(), + BlackBoxFuncCall::MultiScalarMul { .. } => "multi_scalar_mul".to_string(), + BlackBoxFuncCall::EmbeddedCurveAdd { .. } => "embedded_curve_add".to_string(), + BlackBoxFuncCall::Keccakf1600 { .. } => "keccakf1600".to_string(), + BlackBoxFuncCall::RecursiveAggregation { .. } => "recursive_aggregation".to_string(), + BlackBoxFuncCall::BigIntAdd { .. } => "big_int_add".to_string(), + BlackBoxFuncCall::BigIntSub { .. } => "big_int_sub".to_string(), + BlackBoxFuncCall::BigIntMul { .. } => "big_int_mul".to_string(), + BlackBoxFuncCall::BigIntDiv { .. } => "big_int_div".to_string(), + BlackBoxFuncCall::BigIntFromLeBytes { .. } => "big_int_from_le_bytes".to_string(), + BlackBoxFuncCall::BigIntToLeBytes { .. } => "big_int_to_le_bytes".to_string(), + BlackBoxFuncCall::Poseidon2Permutation { .. } => "poseidon2_permutation".to_string(), + BlackBoxFuncCall::Sha256Compression { .. } => "sha256_compression".to_string(), + } +} + +fn format_blackbox_op(call: &BlackBoxOp) -> String { + match call { + BlackBoxOp::AES128Encrypt { .. } => "aes128_encrypt".to_string(), + BlackBoxOp::Blake2s { .. } => "blake2s".to_string(), + BlackBoxOp::Blake3 { .. } => "blake3".to_string(), + BlackBoxOp::EcdsaSecp256k1 { .. } => "ecdsa_secp256k1".to_string(), + BlackBoxOp::EcdsaSecp256r1 { .. } => "ecdsa_secp256r1".to_string(), + BlackBoxOp::MultiScalarMul { .. } => "multi_scalar_mul".to_string(), + BlackBoxOp::EmbeddedCurveAdd { .. } => "embedded_curve_add".to_string(), + BlackBoxOp::Keccakf1600 { .. } => "keccakf1600".to_string(), + BlackBoxOp::BigIntAdd { .. } => "big_int_add".to_string(), + BlackBoxOp::BigIntSub { .. } => "big_int_sub".to_string(), + BlackBoxOp::BigIntMul { .. } => "big_int_mul".to_string(), + BlackBoxOp::BigIntDiv { .. } => "big_int_div".to_string(), + BlackBoxOp::BigIntFromLeBytes { .. } => "big_int_from_le_bytes".to_string(), + BlackBoxOp::BigIntToLeBytes { .. } => "big_int_to_le_bytes".to_string(), + BlackBoxOp::Poseidon2Permutation { .. } => "poseidon2_permutation".to_string(), + BlackBoxOp::Sha256Compression { .. } => "sha256_compression".to_string(), + BlackBoxOp::ToRadix { .. } => "to_radix".to_string(), + } +} + +fn format_acir_opcode_kind(opcode: &AcirOpcode) -> String { + match opcode { + AcirOpcode::AssertZero(_) => "arithmetic".to_string(), + AcirOpcode::BlackBoxFuncCall(call) => { + format!("blackbox::{}", format_blackbox_function(call)) + } + AcirOpcode::MemoryOp { .. } => "memory::op".to_string(), + AcirOpcode::MemoryInit { .. } => "memory::init".to_string(), + AcirOpcode::BrilligCall { id, .. } => format!("brillig_call({id})"), + AcirOpcode::Call { .. } => "acir_call".to_string(), + } +} + +fn format_binary_field_op(op: &BinaryFieldOp) -> String { + match op { + BinaryFieldOp::Add => "add".to_string(), + BinaryFieldOp::Sub => "sub".to_string(), + BinaryFieldOp::Mul => "mul".to_string(), + BinaryFieldOp::Div => "fdiv".to_string(), + BinaryFieldOp::IntegerDiv => "div".to_string(), + BinaryFieldOp::Equals => "eq".to_string(), + BinaryFieldOp::LessThan => "lt".to_string(), + BinaryFieldOp::LessThanEquals => "lte".to_string(), + } +} + +fn format_binary_int(op: &BinaryIntOp) -> String { + match op { + BinaryIntOp::Add => "add".to_string(), + BinaryIntOp::Sub => "sub".to_string(), + BinaryIntOp::Mul => "mul".to_string(), + BinaryIntOp::Div => "div".to_string(), + BinaryIntOp::Equals => "eq".to_string(), + BinaryIntOp::LessThan => "lt".to_string(), + BinaryIntOp::LessThanEquals => "lte".to_string(), + BinaryIntOp::And => "and".to_string(), + BinaryIntOp::Or => "or".to_string(), + BinaryIntOp::Xor => "xor".to_string(), + BinaryIntOp::Shl => "shl".to_string(), + BinaryIntOp::Shr => "shr".to_string(), + } +} + +fn format_brillig_opcode_kind(opcode: &BrilligOpcode) -> String { + match opcode { + BrilligOpcode::BinaryFieldOp { op, .. } => format!("field::{}", format_binary_field_op(op)), + BrilligOpcode::BinaryIntOp { op, bit_size, .. } => { + format!("{bit_size}::{}", format_binary_int(op)) + } + BrilligOpcode::Not { .. } => "not".to_string(), + BrilligOpcode::BlackBox(func) => format!("blackbox::{}", format_blackbox_op(func)), + BrilligOpcode::Call { .. } => "call".to_string(), + BrilligOpcode::CalldataCopy { .. } => "calldata_copy".to_string(), + BrilligOpcode::Cast { .. } => "cast".to_string(), + BrilligOpcode::ConditionalMov { .. } => "cmov".to_string(), + BrilligOpcode::Const { .. } => "const".to_string(), + BrilligOpcode::IndirectConst { .. } => "iconst".to_string(), + BrilligOpcode::ForeignCall { function, .. } => format!("foreign_call({})", function), + BrilligOpcode::Jump { .. } => "jump".to_string(), + BrilligOpcode::JumpIf { .. } => "jump_if".to_string(), + BrilligOpcode::JumpIfNot { .. } => "jump_if_not".to_string(), + BrilligOpcode::Load { .. } => "load".to_string(), + BrilligOpcode::Mov { .. } => "mov".to_string(), + BrilligOpcode::Return => "return".to_string(), + BrilligOpcode::Stop { .. } => "stop".to_string(), + BrilligOpcode::Store { .. } => "store".to_string(), + BrilligOpcode::Trap { .. } => "trap".to_string(), + } +} + +pub(crate) fn format_acir_opcode(opcode: &AcirOpcode) -> String { + format!("acir::{}", format_acir_opcode_kind(opcode)) +} + +pub(crate) fn format_brillig_opcode(opcode: &BrilligOpcode) -> String { + format!("brillig::{}", format_brillig_opcode_kind(opcode)) +} diff --git a/tooling/readme.md b/tooling/readme.md new file mode 100644 index 00000000000..3172062241a --- /dev/null +++ b/tooling/readme.md @@ -0,0 +1,15 @@ +# Structure + +Below we briefly describe the purpose of each tool-related crate in this repository. + +## nargo + +This is the default package manager used by Noir. One may draw similarities to Rust's Cargo. + +## nargo_fmt + +This is the default formatter used by Noir, analogous to Rust's rustfmt. + +## lsp + +This is the platform agnostic implementation of Noir's Language Server. It implements the various features supported, but doesn't bind to any particular transport. Binding to a transport must be done when consuming the crate. diff --git a/utils/iter-extended/Cargo.toml b/utils/iter-extended/Cargo.toml new file mode 100644 index 00000000000..4343311506e --- /dev/null +++ b/utils/iter-extended/Cargo.toml @@ -0,0 +1,11 @@ +[package] +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 + +[dependencies] diff --git a/utils/iter-extended/src/lib.rs b/utils/iter-extended/src/lib.rs new file mode 100644 index 00000000000..d2ef271aebf --- /dev/null +++ b/utils/iter-extended/src/lib.rs @@ -0,0 +1,65 @@ +#![forbid(unsafe_code)] +#![warn(unused_crate_dependencies, unused_extern_crates)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] + +use std::collections::BTreeMap; + +/// Equivalent to .into_iter().map(f).collect::>() +pub fn vecmap(iterable: T, f: F) -> Vec +where + T: IntoIterator, + F: FnMut(T::Item) -> U, +{ + iterable.into_iter().map(f).collect() +} + +/// Equivalent to .into_iter().map(f).collect::,_>>() +pub fn try_vecmap(iterable: T, f: F) -> Result, E> +where + T: IntoIterator, + F: FnMut(T::Item) -> Result, +{ + iterable.into_iter().map(f).collect() +} + +/// Equivalent to .into_iter().map(f).collect::>() +pub fn btree_map(iterable: T, f: F) -> BTreeMap +where + T: IntoIterator, + K: std::cmp::Ord, + F: FnMut(T::Item) -> (K, V), +{ + iterable.into_iter().map(f).collect() +} + +/// Equivalent to .into_iter().map(f).collect::,_>>() +pub fn try_btree_map(iterable: T, f: F) -> Result, E> +where + T: IntoIterator, + K: std::cmp::Ord, + F: FnMut(T::Item) -> Result<(K, V), E>, +{ + iterable.into_iter().map(f).collect() +} + +/// Given an iterator over a Result, filter out the Ok values from the Err values +/// and return both in separate `Vec`s. Unlike other collect-like functions over Results, +/// this function will always consume the entire iterator. +pub fn partition_results(iterable: It, mut f: F) -> (Vec, Vec) +where + It: IntoIterator, + F: FnMut(It::Item) -> Result, +{ + let mut oks = vec![]; + let mut errors = vec![]; + + for elem in iterable { + match f(elem) { + Ok(ok) => oks.push(ok), + Err(error) => errors.push(error), + } + } + + (oks, errors) +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000000..77962512b08 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,23294 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 6 + cacheKey: 8 + +"@75lb/deep-merge@npm:^1.1.1": + version: 1.1.1 + resolution: "@75lb/deep-merge@npm:1.1.1" + dependencies: + lodash.assignwith: ^4.2.0 + typical: ^7.1.1 + checksum: fd9063488d854bc5d2e1636426a51d7864d0d32d2d82c5b01a40e89466088680f6e2623345fb46782de438088b6d3f029b0eea6d79a7807e0000b365f6b8142b + languageName: node + linkType: hard + +"@aashutoshrathi/word-wrap@npm:^1.2.3": + version: 1.2.6 + resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" + checksum: ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd + languageName: node + linkType: hard + +"@adraffy/ens-normalize@npm:1.10.0": + version: 1.10.0 + resolution: "@adraffy/ens-normalize@npm:1.10.0" + checksum: af0540f963a2632da2bbc37e36ea6593dcfc607b937857133791781e246d47f870d5e3d21fa70d5cfe94e772c284588c81ea3f5b7f4ea8fbb824369444e4dbcb + languageName: node + linkType: hard + +"@algolia/autocomplete-core@npm:1.9.3": + version: 1.9.3 + resolution: "@algolia/autocomplete-core@npm:1.9.3" + dependencies: + "@algolia/autocomplete-plugin-algolia-insights": 1.9.3 + "@algolia/autocomplete-shared": 1.9.3 + checksum: ce78048568660184a4fa3c6548f344a7f5ce0ba45d4cfc233f9756b6d4f360afd5ae3a18efefcd27a626d3a0d6cf22d9cba3e21b217afae62b8e9d11bc4960da + languageName: node + linkType: hard + +"@algolia/autocomplete-plugin-algolia-insights@npm:1.9.3": + version: 1.9.3 + resolution: "@algolia/autocomplete-plugin-algolia-insights@npm:1.9.3" + dependencies: + "@algolia/autocomplete-shared": 1.9.3 + peerDependencies: + search-insights: ">= 1 < 3" + checksum: 030695bf692021c27f52a3d4931efed23032796e326d4ae7957ae91b51c36a10dc2d885fb043909e853f961c994b8e9ff087f50bb918cfa075370562251a199f + languageName: node + linkType: hard + +"@algolia/autocomplete-preset-algolia@npm:1.9.3": + version: 1.9.3 + resolution: "@algolia/autocomplete-preset-algolia@npm:1.9.3" + dependencies: + "@algolia/autocomplete-shared": 1.9.3 + peerDependencies: + "@algolia/client-search": ">= 4.9.1 < 6" + algoliasearch: ">= 4.9.1 < 6" + checksum: 1ab3273d3054b348eed286ad1a54b21807846326485507b872477b827dc688006d4f14233cebd0bf49b2932ec8e29eca6d76e48a3c9e9e963b25153b987549c0 + languageName: node + linkType: hard + +"@algolia/autocomplete-shared@npm:1.9.3": + version: 1.9.3 + resolution: "@algolia/autocomplete-shared@npm:1.9.3" + peerDependencies: + "@algolia/client-search": ">= 4.9.1 < 6" + algoliasearch: ">= 4.9.1 < 6" + checksum: 06014c8b08d30c452de079f48c0235d8fa09904bf511da8dc1b7e491819940fd4ff36b9bf65340242b2e157a26799a3b9aea01feee9c5bf67be3c48d7dff43d7 + languageName: node + linkType: hard + +"@algolia/cache-browser-local-storage@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/cache-browser-local-storage@npm:4.20.0" + dependencies: + "@algolia/cache-common": 4.20.0 + checksum: b9ca7e190ab77ddf4d30d22223345f69fc89899aa6887ee716e4ffcef14c8c9d28b782cb7cc96a0f04eed95a989878a6feca5b9aa6add0cd1846222c3308bb65 + languageName: node + linkType: hard + +"@algolia/cache-common@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/cache-common@npm:4.20.0" + checksum: a46377de8a309feea109aae1283fc9157c73766a4c51e3085870a1fc49f6e33698814379f3bbdf475713fa0663dace86fc90f0466e64469b1b885a0538abace4 + languageName: node + linkType: hard + +"@algolia/cache-in-memory@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/cache-in-memory@npm:4.20.0" + dependencies: + "@algolia/cache-common": 4.20.0 + checksum: 3d67dcfae431605c8b9b1502f14865722f13b97b2822e1e3ed53bbf7bf66a120a825ccf5ed03476ebdf4aa15482dad5bfc6c2c93d81f07f862c373c689f49317 + languageName: node + linkType: hard + +"@algolia/client-account@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-account@npm:4.20.0" + dependencies: + "@algolia/client-common": 4.20.0 + "@algolia/client-search": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: b59e9c7a324bbfba4abdab3f41d333522eb1abce7dab74e69d297acd9ee2a3c60e82e5e9db42e6a46b5ea26a35728533e6e4ff846c631b588ceb73d14dcbc5fb + languageName: node + linkType: hard + +"@algolia/client-analytics@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-analytics@npm:4.20.0" + dependencies: + "@algolia/client-common": 4.20.0 + "@algolia/client-search": 4.20.0 + "@algolia/requester-common": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: 0be4120ab72162e0640e49eedddff81bfc2c590e9a9322d1788b8c01e06fdabcaaaa9cd75b5b516e502deb888d3ba2285ac5e1c3bb91fc9eb552a24a716dc6e3 + languageName: node + linkType: hard + +"@algolia/client-common@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-common@npm:4.20.0" + dependencies: + "@algolia/requester-common": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: 88a27b5f8bba38349e1dbe47634e2ee159a413ff1a3baf6a65fbf244835f8d368e9f0a5ccce8bfe94ec405b38608be5bed45bcb140517f3aba6fe3b7045db373 + languageName: node + linkType: hard + +"@algolia/client-personalization@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-personalization@npm:4.20.0" + dependencies: + "@algolia/client-common": 4.20.0 + "@algolia/requester-common": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: ddb92ebe135564e03db6ac75da7fdc1c7500a0deffb7e41d5a02a413216a06daea008f8062dab606ba8af4c3c34e550354f48e6ea7b048882c385d915643799a + languageName: node + linkType: hard + +"@algolia/client-search@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-search@npm:4.20.0" + dependencies: + "@algolia/client-common": 4.20.0 + "@algolia/requester-common": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: 9fb6624dab6753f336f3207ee2af3558baeec4772ef739b6f6ed6a754c366e2e8d62cbf1cf8b28d5f763bec276a0a5fc36db2bf6f53a707890a411afcf550e92 + languageName: node + linkType: hard + +"@algolia/events@npm:^4.0.1": + version: 4.0.1 + resolution: "@algolia/events@npm:4.0.1" + checksum: 4f63943f4554cfcfed91d8b8c009a49dca192b81056d8c75e532796f64828cd69899852013e81ff3fff07030df8782b9b95c19a3da0845786bdfe22af42442c2 + languageName: node + linkType: hard + +"@algolia/logger-common@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/logger-common@npm:4.20.0" + checksum: 06ed28f76b630c8e7597534b15138ab6f71c10dfc6e13f1fb1b76965b39c88fd1d9cb3fe6bb9d046de6533ebcbe5ad92e751bc36fabe98ceda39d1d5f47bb637 + languageName: node + linkType: hard + +"@algolia/logger-console@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/logger-console@npm:4.20.0" + dependencies: + "@algolia/logger-common": 4.20.0 + checksum: 721dffe37563e2998d4c361f09a05736b4baa141bfb7da25d50f890ba8257ac99845dd94b43d0d6db38e2fdab96508a726e184a00e5b1e83ef18a16da6fc716c + languageName: node + linkType: hard + +"@algolia/requester-browser-xhr@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/requester-browser-xhr@npm:4.20.0" + dependencies: + "@algolia/requester-common": 4.20.0 + checksum: 669790c7dfd491318976b9d61d98d9785880d7385ba33669f3f8b9c66ea88320bcded82d34f58b5df74b2cb8beb62ef48a28d39117f7997be84348c9fa7f6132 + languageName: node + linkType: hard + +"@algolia/requester-common@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/requester-common@npm:4.20.0" + checksum: 8580ffd2be146bbdb5d4a57668bba4a5014f406cb2e5c65f596db6babab46c48d30c6e4732034ee1f987970aa27dcdab567959d654fa5fa74c4bcaf98312a724 + languageName: node + linkType: hard + +"@algolia/requester-node-http@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/requester-node-http@npm:4.20.0" + dependencies: + "@algolia/requester-common": 4.20.0 + checksum: 7857114b59c67e0d22e8a7ff3f755d11534a1602a4fc80802d3b35802777880a4980420914ea4a6e3e21198f5bacb95906289ce1bb9372458bf6a60a723bee59 + languageName: node + linkType: hard + +"@algolia/transporter@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/transporter@npm:4.20.0" + dependencies: + "@algolia/cache-common": 4.20.0 + "@algolia/logger-common": 4.20.0 + "@algolia/requester-common": 4.20.0 + checksum: f834d5c8fcb7dfa9b7044cb81e9fab44a32f9dd0c3868a0f85fe0de4f4d27ad11fdc9c3c78541bc944c2593f4be56517a8ce593309d062b8a46ca0d6fcb5dcbc + languageName: node + linkType: hard + +"@ampproject/remapping@npm:^2.2.0": + version: 2.2.1 + resolution: "@ampproject/remapping@npm:2.2.1" + dependencies: + "@jridgewell/gen-mapping": ^0.3.0 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 03c04fd526acc64a1f4df22651186f3e5ef0a9d6d6530ce4482ec9841269cf7a11dbb8af79237c282d721c5312024ff17529cd72cc4768c11e999b58e2302079 + languageName: node + linkType: hard + +"@aztec/bb.js@npm:0.66.0": + version: 0.66.0 + resolution: "@aztec/bb.js@npm:0.66.0" + dependencies: + comlink: ^4.4.1 + commander: ^10.0.1 + debug: ^4.3.4 + fflate: ^0.8.0 + pako: ^2.1.0 + tslib: ^2.4.0 + bin: + bb.js: dest/node/main.js + checksum: 7295bf6543afe1c2db795a95c7ed40806de63c77e44bb4dacb2ec6a9171d1d34749150844ab47bc2499d06676e623acb408857b6aa9da702d3c576efadb8c906 + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" + dependencies: + "@babel/highlight": ^7.23.4 + chalk: ^2.4.2 + checksum: d90981fdf56a2824a9b14d19a4c0e8db93633fd488c772624b4e83e0ceac6039a27cd298a247c3214faa952bf803ba23696172ae7e7235f3b97f43ba278c569a + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/code-frame@npm:7.24.7" + dependencies: + "@babel/highlight": ^7.24.7 + picocolors: ^1.0.0 + checksum: 830e62cd38775fdf84d612544251ce773d544a8e63df667728cc9e0126eeef14c6ebda79be0f0bc307e8318316b7f58c27ce86702e0a1f5c321d842eb38ffda4 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/compat-data@npm:7.23.5" + checksum: 06ce244cda5763295a0ea924728c09bae57d35713b675175227278896946f922a63edf803c322f855a3878323d48d0255a2a3023409d2a123483c8a69ebb4744 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.25.2, @babel/compat-data@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/compat-data@npm:7.25.4" + checksum: b12a91d27c3731a4b0bdc9312a50b1911f41f7f728aaf0d4b32486e2257fd2cb2d3ea1a295e98449600c48f2c7883a3196ca77cda1cef7d97a10c2e83d037974 + languageName: node + linkType: hard + +"@babel/core@npm:7.12.9": + version: 7.12.9 + resolution: "@babel/core@npm:7.12.9" + dependencies: + "@babel/code-frame": ^7.10.4 + "@babel/generator": ^7.12.5 + "@babel/helper-module-transforms": ^7.12.1 + "@babel/helpers": ^7.12.5 + "@babel/parser": ^7.12.7 + "@babel/template": ^7.12.7 + "@babel/traverse": ^7.12.9 + "@babel/types": ^7.12.7 + convert-source-map: ^1.7.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.1 + json5: ^2.1.2 + lodash: ^4.17.19 + resolve: ^1.3.2 + semver: ^5.4.1 + source-map: ^0.5.0 + checksum: 4d34eca4688214a4eb6bd5dde906b69a7824f17b931f52cd03628a8ac94d8fbe15565aebffdde106e974c8738cd64ac62c6a6060baa7139a06db1f18c4ff872d + languageName: node + linkType: hard + +"@babel/core@npm:^7.18.6, @babel/core@npm:^7.19.6, @babel/core@npm:^7.23.3": + version: 7.23.5 + resolution: "@babel/core@npm:7.23.5" + dependencies: + "@ampproject/remapping": ^2.2.0 + "@babel/code-frame": ^7.23.5 + "@babel/generator": ^7.23.5 + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helpers": ^7.23.5 + "@babel/parser": ^7.23.5 + "@babel/template": ^7.22.15 + "@babel/traverse": ^7.23.5 + "@babel/types": ^7.23.5 + convert-source-map: ^2.0.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.3 + semver: ^6.3.1 + checksum: 5e5dfb1e61f298676f1fca18c646dbf6fb164ca1056b0169b8d42b7f5c35e026d81823582ccb2358e93a61b035e22b3ad37e2abaae4bf43f1ffb93b6ce19466e + languageName: node + linkType: hard + +"@babel/core@npm:^7.21.3": + version: 7.25.2 + resolution: "@babel/core@npm:7.25.2" + dependencies: + "@ampproject/remapping": ^2.2.0 + "@babel/code-frame": ^7.24.7 + "@babel/generator": ^7.25.0 + "@babel/helper-compilation-targets": ^7.25.2 + "@babel/helper-module-transforms": ^7.25.2 + "@babel/helpers": ^7.25.0 + "@babel/parser": ^7.25.0 + "@babel/template": ^7.25.0 + "@babel/traverse": ^7.25.2 + "@babel/types": ^7.25.2 + convert-source-map: ^2.0.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.3 + semver: ^6.3.1 + checksum: 9a1ef604a7eb62195f70f9370cec45472a08114e3934e3eaaedee8fd754edf0730e62347c7b4b5e67d743ce57b5bb8cf3b92459482ca94d06e06246ef021390a + languageName: node + linkType: hard + +"@babel/generator@npm:^7.12.5, @babel/generator@npm:^7.18.7, @babel/generator@npm:^7.23.3, @babel/generator@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/generator@npm:7.23.5" + dependencies: + "@babel/types": ^7.23.5 + "@jridgewell/gen-mapping": ^0.3.2 + "@jridgewell/trace-mapping": ^0.3.17 + jsesc: ^2.5.1 + checksum: 845ddda7cf38a3edf4be221cc8a439dee9ea6031355146a1a74047aa8007bc030305b27d8c68ec9e311722c910610bde38c0e13a9ce55225251e7cb7e7f3edc8 + languageName: node + linkType: hard + +"@babel/generator@npm:^7.25.0, @babel/generator@npm:^7.25.6": + version: 7.25.6 + resolution: "@babel/generator@npm:7.25.6" + dependencies: + "@babel/types": ^7.25.6 + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 + jsesc: ^2.5.1 + checksum: b55975cd664f5602304d868bb34f4ee3bed6f5c7ce8132cd92ff27a46a53a119def28a182d91992e86f75db904f63094a81247703c4dc96e4db0c03fd04bcd68 + languageName: node + linkType: hard + +"@babel/helper-annotate-as-pure@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 53da330f1835c46f26b7bf4da31f7a496dee9fd8696cca12366b94ba19d97421ce519a74a837f687749318f94d1a37f8d1abcbf35e8ed22c32d16373b2f6198d + languageName: node + linkType: hard + +"@babel/helper-annotate-as-pure@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-annotate-as-pure@npm:7.24.7" + dependencies: + "@babel/types": ^7.24.7 + checksum: 6178566099a6a0657db7a7fa601a54fb4731ca0b8614fbdccfd8e523c210c13963649bc8fdfd53ce7dd14d05e3dda2fb22dea5b30113c488b9eb1a906d60212e + languageName: node + linkType: hard + +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.22.15" + dependencies: + "@babel/types": ^7.22.15 + checksum: 639c697a1c729f9fafa2dd4c9af2e18568190299b5907bd4c2d0bc818fcbd1e83ffeecc2af24327a7faa7ac4c34edd9d7940510a5e66296c19bad17001cf5c7a + languageName: node + linkType: hard + +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.24.7" + dependencies: + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 71a6158a9fdebffb82fdc400d5555ba8f2e370cea81a0d578155877bdc4db7d5252b75c43b2fdf3f72b3f68348891f99bd35ae315542daad1b7ace8322b1abcb + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.6": + version: 7.22.15 + resolution: "@babel/helper-compilation-targets@npm:7.22.15" + dependencies: + "@babel/compat-data": ^7.22.9 + "@babel/helper-validator-option": ^7.22.15 + browserslist: ^4.21.9 + lru-cache: ^5.1.1 + semver: ^6.3.1 + checksum: ce85196769e091ae54dd39e4a80c2a9df1793da8588e335c383d536d54f06baf648d0a08fc873044f226398c4ded15c4ae9120ee18e7dfd7c639a68e3cdc9980 + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.24.7, @babel/helper-compilation-targets@npm:^7.24.8, @babel/helper-compilation-targets@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-compilation-targets@npm:7.25.2" + dependencies: + "@babel/compat-data": ^7.25.2 + "@babel/helper-validator-option": ^7.24.8 + browserslist: ^4.23.1 + lru-cache: ^5.1.1 + semver: ^6.3.1 + checksum: aed33c5496cb9db4b5e2d44e26bf8bc474074cc7f7bb5ebe1d4a20fdeb362cb3ba9e1596ca18c7484bcd6e5c3a155ab975e420d520c0ae60df81f9de04d0fd16 + languageName: node + linkType: hard + +"@babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-create-class-features-plugin@npm:7.23.5" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-member-expression-to-functions": ^7.23.0 + "@babel/helper-optimise-call-expression": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.20 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: fe7c6c0baca1838bba76ac1330df47b661d932354115ea9e2ea65b179f80b717987d3c3da7e1525fd648e5f2d86c620efc959cabda4d7562b125a27c3ac780d0 + languageName: node + linkType: hard + +"@babel/helper-create-class-features-plugin@npm:^7.24.7, @babel/helper-create-class-features-plugin@npm:^7.25.0, @babel/helper-create-class-features-plugin@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/helper-create-class-features-plugin@npm:7.25.4" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + "@babel/helper-member-expression-to-functions": ^7.24.8 + "@babel/helper-optimise-call-expression": ^7.24.7 + "@babel/helper-replace-supers": ^7.25.0 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + "@babel/traverse": ^7.25.4 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 4544ebda4516eb25efdebd47ca024bd7bdb1eb6e7cc3ad89688c8ef8e889734c2f4411ed78981899c641394f013f246f2af63d92a0e9270f6c453309b4cb89ba + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.15, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": + version: 7.22.15 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.15" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + regexpu-core: ^5.3.1 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 0243b8d4854f1dc8861b1029a46d3f6393ad72f366a5a08e36a4648aa682044f06da4c6e87a456260e1e1b33c999f898ba591a0760842c1387bcc93fbf2151a6 + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.24.7, @babel/helper-create-regexp-features-plugin@npm:^7.25.0, @babel/helper-create-regexp-features-plugin@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.25.2" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + regexpu-core: ^5.3.1 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: df55fdc6a1f3090dd37d91347df52d9322d52affa239543808dc142f8fe35e6787e67d8612337668198fac85826fafa9e6772e6c28b7d249ec94e6fafae5da6e + languageName: node + linkType: hard + +"@babel/helper-define-polyfill-provider@npm:^0.4.3": + version: 0.4.3 + resolution: "@babel/helper-define-polyfill-provider@npm:0.4.3" + dependencies: + "@babel/helper-compilation-targets": ^7.22.6 + "@babel/helper-plugin-utils": ^7.22.5 + debug: ^4.1.1 + lodash.debounce: ^4.0.8 + resolve: ^1.14.2 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 5d21e3f47b320e4b5b644195ec405e7ebc3739e48e65899efc808c5fa9c3bf5b06ce0d8ff5246ca99d1411e368f4557bc66730196c5781a5c4e986ee703bee79 + languageName: node + linkType: hard + +"@babel/helper-define-polyfill-provider@npm:^0.6.2": + version: 0.6.2 + resolution: "@babel/helper-define-polyfill-provider@npm:0.6.2" + dependencies: + "@babel/helper-compilation-targets": ^7.22.6 + "@babel/helper-plugin-utils": ^7.22.5 + debug: ^4.1.1 + lodash.debounce: ^4.0.8 + resolve: ^1.14.2 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 2bba965ea9a4887ddf9c11d51d740ab473bd7597b787d042c325f6a45912dfe908c2d6bb1d837bf82f7e9fa51e6ad5150563c58131d2bb85515e63d971414a9c + languageName: node + linkType: hard + +"@babel/helper-environment-visitor@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-environment-visitor@npm:7.22.20" + checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 + languageName: node + linkType: hard + +"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" + dependencies: + "@babel/template": ^7.22.15 + "@babel/types": ^7.23.0 + checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10 + languageName: node + linkType: hard + +"@babel/helper-hoist-variables@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-hoist-variables@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc + languageName: node + linkType: hard + +"@babel/helper-member-expression-to-functions@npm:^7.22.15, @babel/helper-member-expression-to-functions@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" + dependencies: + "@babel/types": ^7.23.0 + checksum: 494659361370c979ada711ca685e2efe9460683c36db1b283b446122596602c901e291e09f2f980ecedfe6e0f2bd5386cb59768285446530df10c14df1024e75 + languageName: node + linkType: hard + +"@babel/helper-member-expression-to-functions@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-member-expression-to-functions@npm:7.24.8" + dependencies: + "@babel/traverse": ^7.24.8 + "@babel/types": ^7.24.8 + checksum: bf923d05d81b06857f4ca4fe9c528c9c447a58db5ea39595bb559eae2fce01a8266173db0fd6a2ec129d7bbbb9bb22f4e90008252f7c66b422c76630a878a4bc + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-module-imports@npm:7.22.15" + dependencies: + "@babel/types": ^7.22.15 + checksum: ecd7e457df0a46f889228f943ef9b4a47d485d82e030676767e6a2fdcbdaa63594d8124d4b55fd160b41c201025aec01fc27580352b1c87a37c9c6f33d116702 + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-module-imports@npm:7.24.7" + dependencies: + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 8ac15d96d262b8940bc469052a048e06430bba1296369be695fabdf6799f201dd0b00151762b56012a218464e706bc033f27c07f6cec20c6f8f5fd6543c67054 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.12.1, @babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-simple-access": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/helper-validator-identifier": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 5d0895cfba0e16ae16f3aa92fee108517023ad89a855289c4eb1d46f7aef4519adf8e6f971e1d55ac20c5461610e17213f1144097a8f932e768a9132e2278d71 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8, @babel/helper-module-transforms@npm:^7.25.0, @babel/helper-module-transforms@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/helper-module-transforms@npm:7.25.2" + dependencies: + "@babel/helper-module-imports": ^7.24.7 + "@babel/helper-simple-access": ^7.24.7 + "@babel/helper-validator-identifier": ^7.24.7 + "@babel/traverse": ^7.25.2 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 282d4e3308df6746289e46e9c39a0870819630af5f84d632559171e4fae6045684d771a65f62df3d569e88ccf81dc2def78b8338a449ae3a94bb421aa14fc367 + languageName: node + linkType: hard + +"@babel/helper-optimise-call-expression@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: c70ef6cc6b6ed32eeeec4482127e8be5451d0e5282d5495d5d569d39eb04d7f1d66ec99b327f45d1d5842a9ad8c22d48567e93fc502003a47de78d122e355f7c + languageName: node + linkType: hard + +"@babel/helper-optimise-call-expression@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-optimise-call-expression@npm:7.24.7" + dependencies: + "@babel/types": ^7.24.7 + checksum: 280654eaf90e92bf383d7eed49019573fb35a98c9e992668f701ad099957246721044be2068cf6840cb2299e0ad393705a1981c88c23a1048096a8d59e5f79a3 + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:7.10.4": + version: 7.10.4 + resolution: "@babel/helper-plugin-utils@npm:7.10.4" + checksum: 639ed8fc462b97a83226cee6bb081b1d77e7f73e8b033d2592ed107ee41d96601e321e5ea53a33e47469c7f1146b250a3dcda5ab873c7de162ab62120c341a41 + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": + version: 7.22.5 + resolution: "@babel/helper-plugin-utils@npm:7.22.5" + checksum: c0fc7227076b6041acd2f0e818145d2e8c41968cc52fb5ca70eed48e21b8fe6dd88a0a91cbddf4951e33647336eb5ae184747ca706817ca3bef5e9e905151ff5 + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-plugin-utils@npm:7.24.8" + checksum: 73b1a83ba8bcee21dc94de2eb7323207391715e4369fd55844bb15cf13e3df6f3d13a40786d990e6370bf0f571d94fc31f70dec96c1d1002058258c35ca3767a + languageName: node + linkType: hard + +"@babel/helper-remap-async-to-generator@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-remap-async-to-generator@npm:7.22.20" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-wrap-function": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 2fe6300a6f1b58211dffa0aed1b45d4958506d096543663dba83bd9251fe8d670fa909143a65b45e72acb49e7e20fbdb73eae315d9ddaced467948c3329986e7 + languageName: node + linkType: hard + +"@babel/helper-remap-async-to-generator@npm:^7.24.7, @babel/helper-remap-async-to-generator@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helper-remap-async-to-generator@npm:7.25.0" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + "@babel/helper-wrap-function": ^7.25.0 + "@babel/traverse": ^7.25.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 47f3065e43fe9d6128ddb4291ffb9cf031935379265fd13de972b5f241943121f7583efb69cd2e1ecf39e3d0f76f047547d56c3fcc2c853b326fad5465da0bd7 + languageName: node + linkType: hard + +"@babel/helper-replace-supers@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-replace-supers@npm:7.22.20" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-member-expression-to-functions": ^7.22.15 + "@babel/helper-optimise-call-expression": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: a0008332e24daedea2e9498733e3c39b389d6d4512637e000f96f62b797e702ee24a407ccbcd7a236a551590a38f31282829a8ef35c50a3c0457d88218cae639 + languageName: node + linkType: hard + +"@babel/helper-replace-supers@npm:^7.24.7, @babel/helper-replace-supers@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helper-replace-supers@npm:7.25.0" + dependencies: + "@babel/helper-member-expression-to-functions": ^7.24.8 + "@babel/helper-optimise-call-expression": ^7.24.7 + "@babel/traverse": ^7.25.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: f669fc2487c22d40b808f94b9c3ee41129484d5ef0ba689bdd70f216ff91e10b6b021d2f8cd37e7bdd700235a2a6ae6622526344f064528190383bf661ac65f8 + languageName: node + linkType: hard + +"@babel/helper-simple-access@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-simple-access@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: fe9686714caf7d70aedb46c3cce090f8b915b206e09225f1e4dbc416786c2fdbbee40b38b23c268b7ccef749dd2db35f255338fb4f2444429874d900dede5ad2 + languageName: node + linkType: hard + +"@babel/helper-simple-access@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-simple-access@npm:7.24.7" + dependencies: + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: ddbf55f9dea1900213f2a1a8500fabfd21c5a20f44dcfa957e4b0d8638c730f88751c77f678644f754f1a1dc73f4eb8b766c300deb45a9daad000e4247957819 + languageName: node + linkType: hard + +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 1012ef2295eb12dc073f2b9edf3425661e9b8432a3387e62a8bc27c42963f1f216ab3124228015c748770b2257b4f1fda882ca8fa34c0bf485e929ae5bc45244 + languageName: node + linkType: hard + +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.24.7" + dependencies: + "@babel/traverse": ^7.24.7 + "@babel/types": ^7.24.7 + checksum: 11b28fe534ce2b1a67c4d8e51a7b5711a2a0a0cae802f74614eee54cca58c744d9a62f6f60103c41759e81c537d270bfd665bf368a6bea214c6052f2094f8407 + languageName: node + linkType: hard + +"@babel/helper-split-export-declaration@npm:^7.22.6": + version: 7.22.6 + resolution: "@babel/helper-split-export-declaration@npm:7.22.6" + dependencies: + "@babel/types": ^7.22.5 + checksum: e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 + languageName: node + linkType: hard + +"@babel/helper-string-parser@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/helper-string-parser@npm:7.23.4" + checksum: c0641144cf1a7e7dc93f3d5f16d5327465b6cf5d036b48be61ecba41e1eece161b48f46b7f960951b67f8c3533ce506b16dece576baef4d8b3b49f8c65410f90 + languageName: node + linkType: hard + +"@babel/helper-string-parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-string-parser@npm:7.24.8" + checksum: 39b03c5119216883878655b149148dc4d2e284791e969b19467a9411fccaa33f7a713add98f4db5ed519535f70ad273cdadfd2eb54d47ebbdeac5083351328ce + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-validator-identifier@npm:7.24.7" + checksum: 6799ab117cefc0ecd35cd0b40ead320c621a298ecac88686a14cffceaac89d80cdb3c178f969861bf5fa5e4f766648f9161ea0752ecfe080d8e89e3147270257 + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-validator-option@npm:7.23.5" + checksum: 537cde2330a8aede223552510e8a13e9c1c8798afee3757995a7d4acae564124fe2bf7e7c3d90d62d3657434a74340a274b3b3b1c6f17e9a2be1f48af29cb09e + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.24.7, @babel/helper-validator-option@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-validator-option@npm:7.24.8" + checksum: a52442dfa74be6719c0608fee3225bd0493c4057459f3014681ea1a4643cd38b68ff477fe867c4b356da7330d085f247f0724d300582fa4ab9a02efaf34d107c + languageName: node + linkType: hard + +"@babel/helper-wrap-function@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-wrap-function@npm:7.22.20" + dependencies: + "@babel/helper-function-name": ^7.22.5 + "@babel/template": ^7.22.15 + "@babel/types": ^7.22.19 + checksum: 221ed9b5572612aeb571e4ce6a256f2dee85b3c9536f1dd5e611b0255e5f59a3d0ec392d8d46d4152149156a8109f92f20379b1d6d36abb613176e0e33f05fca + languageName: node + linkType: hard + +"@babel/helper-wrap-function@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/helper-wrap-function@npm:7.25.0" + dependencies: + "@babel/template": ^7.25.0 + "@babel/traverse": ^7.25.0 + "@babel/types": ^7.25.0 + checksum: 0095b4741704066d1687f9bbd5370bb88c733919e4275e49615f70c180208148ff5f24ab58d186ce92f8f5d28eab034ec6617e9264590cc4744c75302857629c + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.12.5, @babel/helpers@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helpers@npm:7.23.5" + dependencies: + "@babel/template": ^7.22.15 + "@babel/traverse": ^7.23.5 + "@babel/types": ^7.23.5 + checksum: c16dc8a3bb3d0e02c7ee1222d9d0865ed4b92de44fb8db43ff5afd37a0fc9ea5e2906efa31542c95b30c1a3a9540d66314663c9a23b5bb9b5ec76e8ebc896064 + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.25.0": + version: 7.25.6 + resolution: "@babel/helpers@npm:7.25.6" + dependencies: + "@babel/template": ^7.25.0 + "@babel/types": ^7.25.6 + checksum: 5a548999db82049a5f7ac6de57576b4ed0d386ce07d058151698836ed411eae6230db12535487caeebb68a2ffc964491e8aead62364a5132ab0ae20e8b68e19f + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" + dependencies: + "@babel/helper-validator-identifier": ^7.22.20 + chalk: ^2.4.2 + js-tokens: ^4.0.0 + checksum: 643acecdc235f87d925979a979b539a5d7d1f31ae7db8d89047269082694122d11aa85351304c9c978ceeb6d250591ccadb06c366f358ccee08bb9c122476b89 + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/highlight@npm:7.24.7" + dependencies: + "@babel/helper-validator-identifier": ^7.24.7 + chalk: ^2.4.2 + js-tokens: ^4.0.0 + picocolors: ^1.0.0 + checksum: 5cd3a89f143671c4ac129960024ba678b669e6fc673ce078030f5175002d1d3d52bc10b22c5b916a6faf644b5028e9a4bd2bb264d053d9b05b6a98690f1d46f1 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.12.7, @babel/parser@npm:^7.18.8, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/parser@npm:7.23.5" + bin: + parser: ./bin/babel-parser.js + checksum: ea763629310f71580c4a3ea9d3705195b7ba994ada2cc98f9a584ebfdacf54e92b2735d351672824c2c2b03c7f19206899f4d95650d85ce514a822b19a8734c7 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.25.0, @babel/parser@npm:^7.25.6": + version: 7.25.6 + resolution: "@babel/parser@npm:7.25.6" + dependencies: + "@babel/types": ^7.25.6 + bin: + parser: ./bin/babel-parser.js + checksum: 85b237ded09ee43cc984493c35f3b1ff8a83e8dbbb8026b8132e692db6567acc5a1659ec928e4baa25499ddd840d7dae9dee3062be7108fe23ec5f94a8066b1e + languageName: node + linkType: hard + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.25.3": + version: 7.25.3 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.25.3" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/traverse": ^7.25.3 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: d3dba60f360defe70eb43e35a1b17ea9dd4a99e734249e15be3d5c288019644f96f88d7ff51990118fda0845b4ad50f6d869e0382232b1d8b054d113d4eea7e2 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: fd56d1e6435f2c008ca9050ea906ff7eedcbec43f532f2bf2e7e905d8bf75bf5e4295ea9593f060394e2c8e45737266ccbf718050bad2dd7be4e7613c60d1b5b + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: ddbaf2c396b7780f15e80ee01d6dd790db076985f3dfeb6527d1a8d4cacf370e49250396a3aa005b2c40233cac214a106232f83703d5e8491848bde273938232 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 13ed301b108d85867d64226bbc4032b07dd1a23aab68e9e32452c4fe3930f2198bb65bdae9c262c4104bd5e45647bc1830d25d43d356ee9a137edd8d5fab8350 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-transform-optional-chaining": ^7.23.3 + peerDependencies: + "@babel/core": ^7.13.0 + checksum: 434b9d710ae856fa1a456678cc304fbc93915af86d581ee316e077af746a709a741ea39d7e1d4f5b98861b629cc7e87f002d3138f5e836775632466d4c74aef2 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + "@babel/plugin-transform-optional-chaining": ^7.24.7 + peerDependencies: + "@babel/core": ^7.13.0 + checksum: 07b92878ac58a98ea1fdf6a8b4ec3413ba4fa66924e28b694d63ec5b84463123fbf4d7153b56cf3cedfef4a3482c082fe3243c04f8fb2c041b32b0e29b4a9e21 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 4690123f0ef7c11d6bf1a9579e4f463ce363563b75ec3f6ca66cf68687e39d8d747a82c833847653962f79da367eca895d9095c60d8ebb224a1d4277003acc11 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/traverse": ^7.25.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: c8d08b8d6cc71451ad2a50cf7db72ab5b41c1e5e2e4d56cf6837a25a61270abd682c6b8881ab025f11a552d2024b3780519bb051459ebb71c27aed13d9917663 + languageName: node + linkType: hard + +"@babel/plugin-proposal-object-rest-spread@npm:7.12.1": + version: 7.12.1 + resolution: "@babel/plugin-proposal-object-rest-spread@npm:7.12.1" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + "@babel/plugin-syntax-object-rest-spread": ^7.8.0 + "@babel/plugin-transform-parameters": ^7.12.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 221a41630c9a7162bf0416c71695b3f7f38482078a1d0d3af7abdc4f07ea1c9feed890399158d56c1d0278c971fe6f565ce822e9351e4481f7d98e9ff735dced + languageName: node + linkType: hard + +"@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2": + version: 7.21.0-placeholder-for-preset-env.2 + resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d97745d098b835d55033ff3a7fb2b895b9c5295b08a5759e4f20df325aa385a3e0bc9bd5ad8f2ec554a44d4e6525acfc257b8c5848a1345cb40f26a30e277e91 + languageName: node + linkType: hard + +"@babel/plugin-syntax-async-generators@npm:^7.8.4": + version: 7.8.4 + resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7ed1c1d9b9e5b64ef028ea5e755c0be2d4e5e4e3d6cf7df757b9a8c4cfa4193d268176d0f1f7fbecdda6fe722885c7fda681f480f3741d8a2d26854736f05367 + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-properties@npm:^7.12.13": + version: 7.12.13 + resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" + dependencies: + "@babel/helper-plugin-utils": ^7.12.13 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 24f34b196d6342f28d4bad303612d7ff566ab0a013ce89e775d98d6f832969462e7235f3e7eaf17678a533d4be0ba45d3ae34ab4e5a9dcbda5d98d49e5efa2fc + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-static-block@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3e80814b5b6d4fe17826093918680a351c2d34398a914ce6e55d8083d72a9bdde4fbaf6a2dcea0e23a03de26dc2917ae3efd603d27099e2b98380345703bf948 + languageName: node + linkType: hard + +"@babel/plugin-syntax-dynamic-import@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-dynamic-import@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ce307af83cf433d4ec42932329fad25fa73138ab39c7436882ea28742e1c0066626d224e0ad2988724c82644e41601cef607b36194f695cb78a1fcdc959637bd + languageName: node + linkType: hard + +"@babel/plugin-syntax-export-namespace-from@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-export-namespace-from@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 85740478be5b0de185228e7814451d74ab8ce0a26fcca7613955262a26e99e8e15e9da58f60c754b84515d4c679b590dbd3f2148f0f58025f4ae706f1c5a5d4a + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-assertions@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 883e6b35b2da205138caab832d54505271a3fee3fc1e8dc0894502434fc2b5d517cbe93bbfbfef8068a0fb6ec48ebc9eef3f605200a489065ba43d8cddc1c9a7 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-assertions@npm:^7.24.7": + version: 7.25.6 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.25.6" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b3b251ace9f184c2d6369cde686ff01581050cb0796f2ff00ff4021f31cf86270b347df09579f2c0996e999e37e1dddafacec42ed1ef6aae21a265aff947e792 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-attributes@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9aed7661ffb920ca75df9f494757466ca92744e43072e0848d87fa4aa61a3f2ee5a22198ac1959856c036434b5614a8f46f1fb70298835dbe28220cdd1d4c11e + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-attributes@npm:^7.24.7": + version: 7.25.6 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.25.6" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3b0928e73e42346e8a65760a3ff853c87ad693cdf11bb335a23e895e0b5b1f0601118521b3aff2a6946488a580a63afb6a5b5686153a7678b4dff0e4e4604dd7 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 166ac1125d10b9c0c430e4156249a13858c0366d38844883d75d27389621ebe651115cb2ceb6dc011534d5055719fa1727b59f39e1ab3ca97820eef3dcab5b9b + languageName: node + linkType: hard + +"@babel/plugin-syntax-json-strings@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-json-strings@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bf5aea1f3188c9a507e16efe030efb996853ca3cadd6512c51db7233cc58f3ac89ff8c6bdfb01d30843b161cfe7d321e1bf28da82f7ab8d7e6bc5464666f354a + languageName: node + linkType: hard + +"@babel/plugin-syntax-jsx@npm:7.12.1": + version: 7.12.1 + resolution: "@babel/plugin-syntax-jsx@npm:7.12.1" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d4b9b589c484b2e0856799770f060dff34c67b24d7f4526f66309a0e0e9cf388a5c1f2c0da329d1973cc87d1b2cede8f3dc8facfac59e785d6393a003bcdd0f9 + languageName: node + linkType: hard + +"@babel/plugin-syntax-jsx@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 89037694314a74e7f0e7a9c8d3793af5bf6b23d80950c29b360db1c66859d67f60711ea437e70ad6b5b4b29affe17eababda841b6c01107c2b638e0493bafb4e + languageName: node + linkType: hard + +"@babel/plugin-syntax-jsx@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-syntax-jsx@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7a5ca629d8ca1e1ee78705a78e58c12920d07ed8006d7e7232b31296a384ff5e41d7b649bde5561196041037bbb9f9715be1d1c20975df87ca204f34ad15b965 + languageName: node + linkType: hard + +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: aff33577037e34e515911255cdbb1fd39efee33658aa00b8a5fd3a4b903585112d037cce1cc9e4632f0487dc554486106b79ccd5ea63a2e00df4363f6d4ff886 + languageName: node + linkType: hard + +"@babel/plugin-syntax-nullish-coalescing-operator@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-nullish-coalescing-operator@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 87aca4918916020d1fedba54c0e232de408df2644a425d153be368313fdde40d96088feed6c4e5ab72aac89be5d07fef2ddf329a15109c5eb65df006bf2580d1 + languageName: node + linkType: hard + +"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 01ec5547bd0497f76cc903ff4d6b02abc8c05f301c88d2622b6d834e33a5651aa7c7a3d80d8d57656a4588f7276eba357f6b7e006482f5b564b7a6488de493a1 + languageName: node + linkType: hard + +"@babel/plugin-syntax-object-rest-spread@npm:7.8.3, @babel/plugin-syntax-object-rest-spread@npm:^7.8.0, @babel/plugin-syntax-object-rest-spread@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fddcf581a57f77e80eb6b981b10658421bc321ba5f0a5b754118c6a92a5448f12a0c336f77b8abf734841e102e5126d69110a306eadb03ca3e1547cab31f5cbf + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-catch-binding@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-catch-binding@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 910d90e72bc90ea1ce698e89c1027fed8845212d5ab588e35ef91f13b93143845f94e2539d831dc8d8ededc14ec02f04f7bd6a8179edd43a326c784e7ed7f0b9 + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-chaining@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-chaining@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: eef94d53a1453361553c1f98b68d17782861a04a392840341bc91780838dd4e695209c783631cf0de14c635758beafb6a3a65399846ffa4386bff90639347f30 + languageName: node + linkType: hard + +"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b317174783e6e96029b743ccff2a67d63d38756876e7e5d0ba53a322e38d9ca452c13354a57de1ad476b4c066dbae699e0ca157441da611117a47af88985ecda + languageName: node + linkType: hard + +"@babel/plugin-syntax-top-level-await@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bbd1a56b095be7820029b209677b194db9b1d26691fe999856462e66b25b281f031f3dfd91b1619e9dcf95bebe336211833b854d0fb8780d618e35667c2d0d7e + languageName: node + linkType: hard + +"@babel/plugin-syntax-typescript@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: abfad3a19290d258b028e285a1f34c9b8a0cbe46ef79eafed4ed7ffce11b5d0720b5e536c82f91cbd8442cde35a3dd8e861fa70366d87ff06fdc0d4756e30876 + languageName: node + linkType: hard + +"@babel/plugin-syntax-typescript@npm:^7.24.7": + version: 7.25.4 + resolution: "@babel/plugin-syntax-typescript@npm:7.25.4" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9b89b8930cd5983f64251d75c9fcdc17a8dc73837d6de12220ff972888ecff4054a6467cf0c423cad242aa96c0f0564a39a0823073728cc02239b80d13f02230 + languageName: node + linkType: hard + +"@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: a651d700fe63ff0ddfd7186f4ebc24447ca734f114433139e3c027bc94a900d013cf1ef2e2db8430425ba542e39ae160c3b05f06b59fd4656273a3df97679e9c + languageName: node + linkType: hard + +"@babel/plugin-transform-arrow-functions@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 1e99118176e5366c2636064d09477016ab5272b2a92e78b8edb571d20bc3eaa881789a905b20042942c3c2d04efc530726cf703f937226db5ebc495f5d067e66 + languageName: node + linkType: hard + +"@babel/plugin-transform-arrow-functions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 707c209b5331c7dc79bd326128c6a6640dbd62a78da1653c844db20c4f36bf7b68454f1bc4d2d051b3fde9136fa291f276ec03a071bb00ee653069ff82f91010 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-generator-functions@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.4" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-remap-async-to-generator": ^7.22.20 + "@babel/plugin-syntax-async-generators": ^7.8.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e2fc132c9033711d55209f4781e1fc73f0f4da5e0ca80a2da73dec805166b73c92a6e83571a8994cd2c893a28302e24107e90856202b24781bab734f800102bb + languageName: node + linkType: hard + +"@babel/plugin-transform-async-generator-functions@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.25.4" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-remap-async-to-generator": ^7.25.0 + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/traverse": ^7.25.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4235444735a1946f8766fe56564a8134c2c36c73e6cf83b3f2ed5624ebc84ff5979506a6a5b39acdb23aa09d442a6af471710ed408ccce533a2c4d2990b9df6a + languageName: node + linkType: hard + +"@babel/plugin-transform-async-to-generator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.23.3" + dependencies: + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-remap-async-to-generator": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2e9d9795d4b3b3d8090332104e37061c677f29a1ce65bcbda4099a32d243e5d9520270a44bbabf0fb1fb40d463bd937685b1a1042e646979086c546d55319c3c + languageName: node + linkType: hard + +"@babel/plugin-transform-async-to-generator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.24.7" + dependencies: + "@babel/helper-module-imports": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-remap-async-to-generator": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 13704fb3b83effc868db2b71bfb2c77b895c56cb891954fc362e95e200afd523313b0e7cf04ce02f45b05e76017c5b5fa8070c92613727a35131bb542c253a36 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoped-functions@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e63b16d94ee5f4d917e669da3db5ea53d1e7e79141a2ec873c1e644678cdafe98daa556d0d359963c827863d6b3665d23d4938a94a4c5053a1619c4ebd01d020 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoped-functions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 249cdcbff4e778b177245f9652b014ea4f3cd245d83297f10a7bf6d97790074089aa62bcde8c08eb299c5e68f2faed346b587d3ebac44d625ba9a83a4ee27028 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoping@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fc4b2100dd9f2c47d694b4b35ae8153214ccb4e24ef545c259a9db17211b18b6a430f22799b56db8f6844deaeaa201af45a03331d0c80cc28b0c4e3c814570e4 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoping@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-block-scoping@npm:7.25.0" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b1a8f932f69ad2a47ae3e02b4cedd2a876bfc2ac9cf72a503fd706cdc87272646fe9eed81e068c0fc639647033de29f7fa0c21cddd1da0026f83dbaac97316a8 + languageName: node + linkType: hard + +"@babel/plugin-transform-class-properties@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-class-properties@npm:7.23.3" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9c6f8366f667897541d360246de176dd29efc7a13d80a5b48361882f7173d9173be4646c3b7d9b003ccc0e01e25df122330308f33db921fa553aa17ad544b3fc + languageName: node + linkType: hard + +"@babel/plugin-transform-class-properties@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-class-properties@npm:7.25.4" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.25.4 + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b73f7d968639c6c2dfc13f4c5a8fe45cefd260f0faa7890ae12e65d41211072544ff5e128c8b61a86887b29ffd3df8422dbdfbf61648488e71d4bb599c41f4a5 + languageName: node + linkType: hard + +"@babel/plugin-transform-class-static-block@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-class-static-block@npm:7.23.4" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + peerDependencies: + "@babel/core": ^7.12.0 + checksum: c8bfaba19a674fc2eb54edad71e958647360474e3163e8226f1acd63e4e2dbec32a171a0af596c1dc5359aee402cc120fea7abd1fb0e0354b6527f0fc9e8aa1e + languageName: node + linkType: hard + +"@babel/plugin-transform-class-static-block@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-class-static-block@npm:7.24.7" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + peerDependencies: + "@babel/core": ^7.12.0 + checksum: 324049263504f18416f1c3e24033baebfafd05480fdd885c8ebe6f2b415b0fc8e0b98d719360f9e30743cc78ac387fabc0b3c6606d2b54135756ffb92963b382 + languageName: node + linkType: hard + +"@babel/plugin-transform-classes@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/plugin-transform-classes@npm:7.23.5" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-optimise-call-expression": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.20 + "@babel/helper-split-export-declaration": ^7.22.6 + globals: ^11.1.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6d0dd3b0828e84a139a51b368f33f315edee5688ef72c68ba25e0175c68ea7357f9c8810b3f61713e368a3063cdcec94f3a2db952e453b0b14ef428a34aa8169 + languageName: node + linkType: hard + +"@babel/plugin-transform-classes@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-classes@npm:7.25.4" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + "@babel/helper-compilation-targets": ^7.25.2 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-replace-supers": ^7.25.0 + "@babel/traverse": ^7.25.4 + globals: ^11.1.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0bf20e46eeb691bd60cee5d1b01950fc37accec88018ecace25099f7c8d8509c1ac54d11b8caf9f2157c6945969520642a3bc421159c1a14e80224dc9a7611de + languageName: node + linkType: hard + +"@babel/plugin-transform-computed-properties@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-computed-properties@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/template": ^7.22.15 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 80452661dc25a0956f89fe98cb562e8637a9556fb6c00d312c57653ce7df8798f58d138603c7e1aad96614ee9ccd10c47e50ab9ded6b6eded5adeb230d2a982e + languageName: node + linkType: hard + +"@babel/plugin-transform-computed-properties@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-computed-properties@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/template": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0cf8c1b1e4ea57dec8d4612460d84fd4cdbf71a7499bb61ee34632cf89018a59eee818ffca88a8d99ee7057c20a4257044d7d463fda6daef9bf1db9fa81563cb + languageName: node + linkType: hard + +"@babel/plugin-transform-destructuring@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-destructuring@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9e015099877272501162419bfe781689aec5c462cd2aec752ee22288f209eec65969ff11b8fdadca2eaddea71d705d3bba5b9c60752fcc1be67874fcec687105 + languageName: node + linkType: hard + +"@babel/plugin-transform-destructuring@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-destructuring@npm:7.24.8" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0b4bd3d608979a1e5bd97d9d42acd5ad405c7fffa61efac4c7afd8e86ea6c2d91ab2d94b6a98d63919571363fe76e0b03c4ff161f0f60241b895842596e4a999 + languageName: node + linkType: hard + +"@babel/plugin-transform-dotall-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.23.3" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a2dbbf7f1ea16a97948c37df925cb364337668c41a3948b8d91453f140507bd8a3429030c7ce66d09c299987b27746c19a2dd18b6f17dcb474854b14fd9159a3 + languageName: node + linkType: hard + +"@babel/plugin-transform-dotall-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.24.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 67b10fc6abb1f61f0e765288eb4c6d63d1d0f9fc0660e69f6f2170c56fa16bc74e49857afc644beda112b41771cd90cf52df0940d11e97e52617c77c7dcff171 + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-keys@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c2a21c34dc0839590cd945192cbc46fde541a27e140c48fe1808315934664cdbf18db64889e23c4eeb6bad9d3e049482efdca91d29de5734ffc887c4fbabaa16 + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-keys@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d1da2ff85ecb56a63f4ccfd9dc9ae69400d85f0dadf44ecddd9e71c6e5c7a9178e74e3a9637555f415a2bb14551e563f09f98534ab54f53d25e8439fdde6ba2d + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.25.0" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.25.0 + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 608d6b0e77341189508880fd1a9f605a38d0803dd6f678ea3920ab181b17b377f6d5221ae8cf0104c7a044d30d4ddb0366bd064447695671d78457a656bb264f + languageName: node + linkType: hard + +"@babel/plugin-transform-dynamic-import@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 57a722604c430d9f3dacff22001a5f31250e34785d4969527a2ae9160fa86858d0892c5b9ff7a06a04076f8c76c9e6862e0541aadca9c057849961343aab0845 + languageName: node + linkType: hard + +"@babel/plugin-transform-dynamic-import@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 776509ff62ab40c12be814a342fc56a5cc09b91fb63032b2633414b635875fd7da03734657be0f6db2891fe6e3033b75d5ddb6f2baabd1a02e4443754a785002 + languageName: node + linkType: hard + +"@babel/plugin-transform-exponentiation-operator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.23.3" + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 00d05ab14ad0f299160fcf9d8f55a1cc1b740e012ab0b5ce30207d2365f091665115557af7d989cd6260d075a252d9e4283de5f2b247dfbbe0e42ae586e6bf66 + languageName: node + linkType: hard + +"@babel/plugin-transform-exponentiation-operator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.24.7" + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 23c84a23eb56589fdd35a3540f9a1190615be069110a2270865223c03aee3ba4e0fc68fe14850800cf36f0712b26e4964d3026235261f58f0405a29fe8dac9b1 + languageName: node + linkType: hard + +"@babel/plugin-transform-export-namespace-from@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9f770a81bfd03b48d6ba155d452946fd56d6ffe5b7d871e9ec2a0b15e0f424273b632f3ed61838b90015b25bbda988896b7a46c7d964fbf8f6feb5820b309f93 + languageName: node + linkType: hard + +"@babel/plugin-transform-export-namespace-from@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3bd3a10038f10ae0dea1ee42137f3edcf7036b5e9e570a0d1cbd0865f03658990c6c2d84fa2475f87a754e7dc5b46766c16f7ce5c9b32c3040150b6a21233a80 + languageName: node + linkType: hard + +"@babel/plugin-transform-for-of@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-for-of@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a6288122a5091d96c744b9eb23dc1b2d4cce25f109ac1e26a0ea03c4ea60330e6f3cc58530b33ba7369fa07163b71001399a145238b7e92bff6270ef3b9c32a0 + languageName: node + linkType: hard + +"@babel/plugin-transform-for-of@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-for-of@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a53b42dc93ab4b7d1ebd3c695b52be22b3d592f6a3dbdb3dc2fea2c8e0a7e1508fe919864c455cde552aec44ce7518625fccbb70c7063373ca228d884f4f49ea + languageName: node + linkType: hard + +"@babel/plugin-transform-function-name@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-function-name@npm:7.23.3" + dependencies: + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 355c6dbe07c919575ad42b2f7e020f320866d72f8b79181a16f8e0cd424a2c761d979f03f47d583d9471b55dcd68a8a9d829b58e1eebcd572145b934b48975a6 + languageName: node + linkType: hard + +"@babel/plugin-transform-function-name@npm:^7.25.1": + version: 7.25.1 + resolution: "@babel/plugin-transform-function-name@npm:7.25.1" + dependencies: + "@babel/helper-compilation-targets": ^7.24.8 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/traverse": ^7.25.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 743f3ea03bbc5a90944849d5a880b6bd9243dddbde581a46952da76e53a0b74c1e2424133fe8129d7a152c1f8c872bcd27e0b6728d7caadabd1afa7bb892e1e0 + languageName: node + linkType: hard + +"@babel/plugin-transform-json-strings@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-json-strings@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-json-strings": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f9019820233cf8955d8ba346df709a0683c120fe86a24ed1c9f003f2db51197b979efc88f010d558a12e1491210fc195a43cd1c7fee5e23b92da38f793a875de + languageName: node + linkType: hard + +"@babel/plugin-transform-json-strings@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-json-strings@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-json-strings": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 88874d0b7a1ddea66c097fc0abb68801ffae194468aa44b828dde9a0e20ac5d8647943793de86092eabaa2911c96f67a6b373793d4bb9c932ef81b2711c06c2e + languageName: node + linkType: hard + +"@babel/plugin-transform-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-literals@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 519a544cd58586b9001c4c9b18da25a62f17d23c48600ff7a685d75ca9eb18d2c5e8f5476f067f0a8f1fea2a31107eff950b9864833061e6076dcc4bdc3e71ed + languageName: node + linkType: hard + +"@babel/plugin-transform-literals@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/plugin-transform-literals@npm:7.25.2" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 70c9bb40e377a306bd8f500899fb72127e527517914466e95dc6bb53fa7a0f51479db244a54a771b5780fc1eab488fedd706669bf11097b81a23c81ab7423eb1 + languageName: node + linkType: hard + +"@babel/plugin-transform-logical-assignment-operators@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2ae1dc9b4ff3bf61a990ff3accdecb2afe3a0ca649b3e74c010078d1cdf29ea490f50ac0a905306a2bcf9ac177889a39ac79bdcc3a0fdf220b3b75fac18d39b5 + languageName: node + linkType: hard + +"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3367ce0be243704dc6fce23e86a592c4380f01998ee5dd9f94c54b1ef7b971ac6f8a002901eb51599ac6cbdc0d067af8d1a720224fca1c40fde8bb8aab804aac + languageName: node + linkType: hard + +"@babel/plugin-transform-member-expression-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 95cec13c36d447c5aa6b8e4c778b897eeba66dcb675edef01e0d2afcec9e8cb9726baf4f81b4bbae7a782595aed72e6a0d44ffb773272c3ca180fada99bf92db + languageName: node + linkType: hard + +"@babel/plugin-transform-member-expression-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2720c57aa3bf70576146ba7d6ea03227f4611852122d76d237924f7b008dafc952e6ae61a19e5024f26c665f44384bbd378466f01b6bd1305b3564a3b7fb1a5d + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-amd@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-amd@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d163737b6a3d67ea579c9aa3b83d4df4b5c34d9dcdf25f415f027c0aa8cded7bac2750d2de5464081f67a042ad9e1c03930c2fab42acd79f9e57c00cf969ddff + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-amd@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-modules-amd@npm:7.24.7" + dependencies: + "@babel/helper-module-transforms": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f1dd0fb2f46c0f8f21076b8c7ccd5b33a85ce6dcb31518ea4c648d9a5bb2474cd4bd87c9b1b752e68591e24b022e334ba0d07631fef2b6b4d8a4b85cf3d581f5 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-commonjs@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-simple-access": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 720a231ceade4ae4d2632478db4e7fecf21987d444942b72d523487ac8d715ca97de6c8f415c71e939595e1a4776403e7dc24ed68fe9125ad4acf57753c9bff7 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-commonjs@npm:^7.24.7, @babel/plugin-transform-modules-commonjs@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.8" + dependencies: + "@babel/helper-module-transforms": ^7.24.8 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-simple-access": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a4cf95b1639c33382064b44558f73ee5fac023f2a94d16e549d2bb55ceebd5cbc10fcddd505d08cd5bc97f5a64af9fd155512358b7dcf7b1a0082e8945cf21c5 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-systemjs@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.23.3" + dependencies: + "@babel/helper-hoist-variables": ^7.22.5 + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0d2fdd993c785aecac9e0850cd5ed7f7d448f0fbb42992a950cc0590167144df25d82af5aac9a5c99ef913d2286782afa44e577af30c10901c5ee8984910fa1f + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-systemjs@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.25.0" + dependencies: + "@babel/helper-module-transforms": ^7.25.0 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-validator-identifier": ^7.24.7 + "@babel/traverse": ^7.25.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fe673bec08564e491847324bb80a1e6edfb229f5c37e58a094d51e95306e7b098e1d130fc43e992d22debd93b9beac74441ffc3f6ea5d78f6b2535896efa0728 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-umd@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-umd@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 586a7a2241e8b4e753a37af9466a9ffa8a67b4ba9aa756ad7500712c05d8fa9a8c1ed4f7bd25fae2a8265e6cf8fe781ec85a8ee885dd34cf50d8955ee65f12dc + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-umd@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-modules-umd@npm:7.24.7" + dependencies: + "@babel/helper-module-transforms": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9ff1c464892efe042952ba778468bda6131b196a2729615bdcc3f24cdc94014f016a4616ee5643c5845bade6ba698f386833e61056d7201314b13a7fd69fac88 + languageName: node + linkType: hard + +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.22.5" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 3ee564ddee620c035b928fdc942c5d17e9c4b98329b76f9cefac65c111135d925eb94ed324064cd7556d4f5123beec79abea1d4b97d1c8a2a5c748887a2eb623 + languageName: node + linkType: hard + +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.24.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: f1c6c7b5d60a86b6d7e4dd098798e1d393d55e993a0b57a73b53640c7a94985b601a96bdacee063f809a9a700bcea3a2ff18e98fa561554484ac56b761d774bd + languageName: node + linkType: hard + +"@babel/plugin-transform-new-target@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-new-target@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e5053389316fce73ad5201b7777437164f333e24787fbcda4ae489cd2580dbbbdfb5694a7237bad91fabb46b591d771975d69beb1c740b82cb4761625379f00b + languageName: node + linkType: hard + +"@babel/plugin-transform-new-target@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-new-target@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3cb94cd1076b270f768f91fdcf9dd2f6d487f8dbfff3df7ca8d07b915900b86d02769a35ba1407d16fe49499012c8f055e1741299e2c880798b953d942a8fa1b + languageName: node + linkType: hard + +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a27d73ea134d3d9560a6b2e26ab60012fba15f1db95865aa0153c18f5ec82cfef6a7b3d8df74e3c2fca81534fa5efeb6cacaf7b08bdb7d123e3dafdd079886a3 + languageName: node + linkType: hard + +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4a9221356401d87762afbc37a9e8e764afc2daf09c421117537820f8cfbed6876888372ad3a7bcfae2d45c95f026651f050ab4020b777be31d3ffb00908dbdd3 + languageName: node + linkType: hard + +"@babel/plugin-transform-numeric-separator@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6ba0e5db3c620a3ec81f9e94507c821f483c15f196868df13fa454cbac719a5449baf73840f5b6eb7d77311b24a2cf8e45db53700d41727f693d46f7caf3eec3 + languageName: node + linkType: hard + +"@babel/plugin-transform-numeric-separator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 561b5f1d08b2c3f92ce849f092751558b5e6cfeb7eb55c79e7375c34dd9c3066dce5e630bb439affef6adcf202b6cbcaaa23870070276fa5bb429c8f5b8c7514 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-rest-spread@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.23.4" + dependencies: + "@babel/compat-data": ^7.23.3 + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-transform-parameters": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 73fec495e327ca3959c1c03d07a621be09df00036c69fff0455af9a008291677ee9d368eec48adacdc6feac703269a649747568b4af4c4e9f134aa71cc5b378d + languageName: node + linkType: hard + +"@babel/plugin-transform-object-rest-spread@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.24.7" + dependencies: + "@babel/helper-compilation-targets": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-transform-parameters": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 169d257b9800c13e1feb4c37fb05dae84f702e58b342bb76e19e82e6692b7b5337c9923ee89e3916a97c0dd04a3375bdeca14f5e126f110bbacbeb46d1886ca2 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-super@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-object-super@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e495497186f621fa79026e183b4f1fbb172fd9df812cbd2d7f02c05b08adbe58012b1a6eb6dd58d11a30343f6ec80d0f4074f9b501d70aa1c94df76d59164c53 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-super@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-object-super@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-replace-supers": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f71e607a830ee50a22fa1a2686524d3339440cf9dea63032f6efbd865cfe4e35000e1e3f3492459e5c986f7c0c07dc36938bf3ce61fc9ba5f8ab732d0b64ab37 + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-catch-binding@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d50b5ee142cdb088d8b5de1ccf7cea85b18b85d85b52f86618f6e45226372f01ad4cdb29abd4fd35ea99a71fefb37009e0107db7a787dcc21d4d402f97470faf + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-catch-binding@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7229f3a5a4facaab40f4fdfc7faabc157dc38a67d66bed7936599f4bc509e0bff636f847ac2aa45294881fce9cf8a0a460b85d2a465b7b977de9739fce9b18f6 + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-chaining@npm:^7.23.3, @babel/plugin-transform-optional-chaining@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e7a4c08038288057b7a08d68c4d55396ada9278095509ca51ed8dfb72a7f13f26bdd7c5185de21079fe0a9d60d22c227cb32e300d266c1bda40f70eee9f4bc1e + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-chaining@npm:^7.24.7, @babel/plugin-transform-optional-chaining@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.8" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 45e55e3a2fffb89002d3f89aef59c141610f23b60eee41e047380bffc40290b59f64fc649aa7ec5281f73d41b2065410d788acc6afaad2a9f44cad6e8af04442 + languageName: node + linkType: hard + +"@babel/plugin-transform-parameters@npm:^7.12.1, @babel/plugin-transform-parameters@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-parameters@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a735b3e85316d17ec102e3d3d1b6993b429bdb3b494651c9d754e3b7d270462ee1f1a126ccd5e3d871af5e683727e9ef98c9d34d4a42204fffaabff91052ed16 + languageName: node + linkType: hard + +"@babel/plugin-transform-parameters@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-parameters@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ab534b03ac2eff94bc79342b8f39a4584666f5305a6c63c1964afda0b1b004e6b861e49d1683548030defe248e3590d3ff6338ee0552cb90c064f7e1479968c3 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-methods@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-private-methods@npm:7.23.3" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cedc1285c49b5a6d9a3d0e5e413b756ac40b3ac2f8f68bdfc3ae268bc8d27b00abd8bb0861c72756ff5dd8bf1eb77211b7feb5baf4fdae2ebbaabe49b9adc1d0 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-methods@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-private-methods@npm:7.25.4" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.25.4 + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cb1dabfc03e2977990263d65bc8f43a9037dffbb5d9a5f825c00d05447ff68015099408c1531d9dd88f18a41a90f5062dc48f3a1d52b415d2d2ee4827dedff09 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-property-in-object@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.23.4" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fb7adfe94ea97542f250a70de32bddbc3e0b802381c92be947fec83ebffda57e68533c4d0697152719a3496fdd3ebf3798d451c024cd4ac848fc15ac26b70aa7 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-property-in-object@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.24.7" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + "@babel/helper-create-class-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8cee9473095305cc787bb653fd681719b49363281feabf677db8a552e8e41c94441408055d7e5fd5c7d41b315e634fa70b145ad0c7c54456216049df4ed57350 + languageName: node + linkType: hard + +"@babel/plugin-transform-property-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-property-literals@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 16b048c8e87f25095f6d53634ab7912992f78e6997a6ff549edc3cf519db4fca01c7b4e0798530d7f6a05228ceee479251245cdd850a5531c6e6f404104d6cc9 + languageName: node + linkType: hard + +"@babel/plugin-transform-property-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-property-literals@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9aeefc3aab6c6bf9d1fae1cf3a2d38c7d886fd3c6c81b7c608c477f5758aee2e7abf52f32724310fe861da61af934ee2508b78a5b5f234b9740c9134e1c14437 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-constant-elements@npm:^7.18.12": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-constant-elements@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f386fe59657910a00c5d276918765c6a74e52c9a223d79463a4eecd652b4da4a6c0a16710fcf5e17b838c336e0c46b552b79e47c1d6eeebc74a813788e0611f7 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-constant-elements@npm:^7.21.3": + version: 7.25.1 + resolution: "@babel/plugin-transform-react-constant-elements@npm:7.25.1" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6126abf8bc3980c1e27fd217f8b2f226b20cce9be300eaf9d30548556dd1e906b7daa4580d9ae1dae35eb5ed5c98e7222e0cb91efb0a232d05aae5875dcfe55c + languageName: node + linkType: hard + +"@babel/plugin-transform-react-display-name@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-display-name@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7f86964e8434d3ddbd3c81d2690c9b66dbf1cd8bd9512e2e24500e9fa8cf378bc52c0853270b3b82143aba5965aec04721df7abdb768f952b44f5c6e0b198779 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx-development@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.22.5" + dependencies: + "@babel/plugin-transform-react-jsx": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 36bc3ff0b96bb0ef4723070a50cfdf2e72cfd903a59eba448f9fe92fea47574d6f22efd99364413719e1f3fb3c51b6c9b2990b87af088f8486a84b2a5f9e4560 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx@npm:^7.22.15, @babel/plugin-transform-react-jsx@npm:^7.22.5": + version: 7.23.4 + resolution: "@babel/plugin-transform-react-jsx@npm:7.23.4" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-jsx": ^7.23.3 + "@babel/types": ^7.23.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d8b8c52e8e22e833bf77c8d1a53b0a57d1fd52ba9596a319d572de79446a8ed9d95521035bc1175c1589d1a6a34600d2e678fa81d81bac8fac121137097f1f0a + languageName: node + linkType: hard + +"@babel/plugin-transform-react-pure-annotations@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.23.3" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9ea3698b1d422561d93c0187ac1ed8f2367e4250b10e259785ead5aa643c265830fd0f4cf5087a5bedbc4007444c06da2f2006686613220acf0949895f453666 + languageName: node + linkType: hard + +"@babel/plugin-transform-regenerator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-regenerator@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + regenerator-transform: ^0.15.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7fdacc7b40008883871b519c9e5cdea493f75495118ccc56ac104b874983569a24edd024f0f5894ba1875c54ee2b442f295d6241c3280e61c725d0dd3317c8e6 + languageName: node + linkType: hard + +"@babel/plugin-transform-regenerator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-regenerator@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + regenerator-transform: ^0.15.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 20c6c3fb6fc9f407829087316653388d311e8c1816b007609bb09aeef254092a7157adace8b3aaa8f34be752503717cb85c88a5fe482180a9b11bcbd676063be + languageName: node + linkType: hard + +"@babel/plugin-transform-reserved-words@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-reserved-words@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 298c4440ddc136784ff920127cea137168e068404e635dc946ddb5d7b2a27b66f1dd4c4acb01f7184478ff7d5c3e7177a127279479926519042948fb7fa0fa48 + languageName: node + linkType: hard + +"@babel/plugin-transform-reserved-words@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-reserved-words@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3d5876954d5914d7270819479504f30c4bf5452a65c677f44e2dab2db50b3c9d4b47793c45dfad7abf4f377035dd79e4b3f554ae350df9f422201d370ce9f8dd + languageName: node + linkType: hard + +"@babel/plugin-transform-runtime@npm:^7.18.6, @babel/plugin-transform-runtime@npm:^7.22.9": + version: 7.23.4 + resolution: "@babel/plugin-transform-runtime@npm:7.23.4" + dependencies: + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + babel-plugin-polyfill-corejs2: ^0.4.6 + babel-plugin-polyfill-corejs3: ^0.8.5 + babel-plugin-polyfill-regenerator: ^0.5.3 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a1693d27cd5ce17d0917280942a62bbf4ee27f6f0fe7beb33789bdc699cda21e5253997663248b32e8e36c01ccd202f96246413b9328b70a05d4cf64faa3191e + languageName: node + linkType: hard + +"@babel/plugin-transform-shorthand-properties@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5d677a03676f9fff969b0246c423d64d77502e90a832665dc872a5a5e05e5708161ce1effd56bb3c0f2c20a1112fca874be57c8a759d8b08152755519281f326 + languageName: node + linkType: hard + +"@babel/plugin-transform-shorthand-properties@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7b524245814607188212b8eb86d8c850e5974203328455a30881b4a92c364b93353fae14bc2af5b614ef16300b75b8c1d3b8f3a08355985b4794a7feb240adc3 + languageName: node + linkType: hard + +"@babel/plugin-transform-spread@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-spread@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8fd5cac201e77a0b4825745f4e07a25f923842f282f006b3a79223c00f61075c8868d12eafec86b2642cd0b32077cdd32314e27bcb75ee5e6a68c0144140dcf2 + languageName: node + linkType: hard + +"@babel/plugin-transform-spread@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-spread@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4c4254c8b9cceb1a8f975fa9b92257ddb08380a35c0a3721b8f4b9e13a3d82e403af2e0fba577b9f2452dd8f06bc3dea71cc53b1e2c6af595af5db52a13429d6 + languageName: node + linkType: hard + +"@babel/plugin-transform-sticky-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 53e55eb2575b7abfdb4af7e503a2bf7ef5faf8bf6b92d2cd2de0700bdd19e934e5517b23e6dfed94ba50ae516b62f3f916773ef7d9bc81f01503f585051e2949 + languageName: node + linkType: hard + +"@babel/plugin-transform-sticky-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 118fc7a7ebf7c20411b670c8a030535fdfe4a88bc5643bb625a584dbc4c8a468da46430a20e6bf78914246962b0f18f1b9d6a62561a7762c4f34a038a5a77179 + languageName: node + linkType: hard + +"@babel/plugin-transform-template-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-template-literals@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b16c5cb0b8796be0118e9c144d15bdc0d20a7f3f59009c6303a6e9a8b74c146eceb3f05186f5b97afcba7cfa87e34c1585a22186e3d5b22f2fd3d27d959d92b2 + languageName: node + linkType: hard + +"@babel/plugin-transform-template-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-template-literals@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ad44e5826f5a98c1575832dbdbd033adfe683cdff195e178528ead62507564bf02f479b282976cfd3caebad8b06d5fd7349c1cdb880dec3c56daea4f1f179619 + languageName: node + linkType: hard + +"@babel/plugin-transform-typeof-symbol@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0af7184379d43afac7614fc89b1bdecce4e174d52f4efaeee8ec1a4f2c764356c6dba3525c0685231f1cbf435b6dd4ee9e738d7417f3b10ce8bbe869c32f4384 + languageName: node + linkType: hard + +"@babel/plugin-transform-typeof-symbol@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.8" + dependencies: + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8663a8e7347cedf181001d99c88cf794b6598c3d82f324098510fe8fb8bd22113995526a77aa35a3cc5d70ffd0617a59dd0d10311a9bf0e1a3a7d3e59b900c00 + languageName: node + linkType: hard + +"@babel/plugin-transform-typescript@npm:^7.23.3": + version: 7.23.5 + resolution: "@babel/plugin-transform-typescript@npm:7.23.5" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-create-class-features-plugin": ^7.23.5 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-typescript": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d77b5cc22cf48fe461de07e4f058dc9c0d8c4e3ca49de0e3a336a94ab39bfa4f4732598e36c479bec0dd1bf4aff9154bc2dcbfbe3145a751e4771ccae5afaaf8 + languageName: node + linkType: hard + +"@babel/plugin-transform-typescript@npm:^7.24.7": + version: 7.25.2 + resolution: "@babel/plugin-transform-typescript@npm:7.25.2" + dependencies: + "@babel/helper-annotate-as-pure": ^7.24.7 + "@babel/helper-create-class-features-plugin": ^7.25.0 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + "@babel/plugin-syntax-typescript": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b0267128d93560a4350919f7230a3b497e20fb8611d9f04bb3560d6b38877305ccad4c40903160263361c6930a84dbcb5b21b8ea923531bda51f67bffdc2dd0b + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-escapes@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 561c429183a54b9e4751519a3dfba6014431e9cdc1484fad03bdaf96582dfc72c76a4f8661df2aeeae7c34efd0fa4d02d3b83a2f63763ecf71ecc925f9cc1f60 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-escapes@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4af0a193e1ddea6ff82b2b15cc2501b872728050bd625740b813c8062fec917d32d530ff6b41de56c15e7296becdf3336a58db81f5ca8e7c445c1306c52f3e01 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-property-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.23.3" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2298461a194758086d17c23c26c7de37aa533af910f9ebf31ebd0893d4aa317468043d23f73edc782ec21151d3c46cf0ff8098a83b725c49a59de28a1d4d6225 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-property-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.24.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: aae13350c50973f5802ca7906d022a6a0cc0e3aebac9122d0450bbd51e78252d4c2032ad69385e2759fcbdd3aac5d571bd7e26258907f51f8e1a51b53be626c2 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.23.3" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c5f835d17483ba899787f92e313dfa5b0055e3deab332f1d254078a2bba27ede47574b6599fcf34d3763f0c048ae0779dc21d2d8db09295edb4057478dc80a9a + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.24.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.24.7 + "@babel/helper-plugin-utils": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 1cb4e70678906e431da0a05ac3f8350025fee290304ad7482d9cfaa1ca67b2e898654de537c9268efbdad5b80d3ebadf42b4a88ea84609bd8a4cce7b11b48afd + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-sets-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.23.3" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 79d0b4c951955ca68235c87b91ab2b393c96285f8aeaa34d6db416d2ddac90000c9bd6e8c4d82b60a2b484da69930507245035f28ba63c6cae341cf3ba68fdef + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-sets-regex@npm:^7.25.4": + version: 7.25.4 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.25.4" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.25.2 + "@babel/helper-plugin-utils": ^7.24.8 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 6d1a7e9fdde4ffc9a81c0e3f261b96a9a0dfe65da282ec96fe63b36c597a7389feac638f1df2a8a4f8c9128337bba8e984f934e9f19077930f33abf1926759ea + languageName: node + linkType: hard + +"@babel/preset-env@npm:^7.18.6, @babel/preset-env@npm:^7.19.4, @babel/preset-env@npm:^7.22.9": + version: 7.23.5 + resolution: "@babel/preset-env@npm:7.23.5" + dependencies: + "@babel/compat-data": ^7.23.5 + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.23.5 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.23.3 + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.23.3 + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.23.3 + "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/plugin-syntax-class-properties": ^7.12.13 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + "@babel/plugin-syntax-import-assertions": ^7.23.3 + "@babel/plugin-syntax-import-attributes": ^7.23.3 + "@babel/plugin-syntax-import-meta": ^7.10.4 + "@babel/plugin-syntax-json-strings": ^7.8.3 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + "@babel/plugin-syntax-top-level-await": ^7.14.5 + "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 + "@babel/plugin-transform-arrow-functions": ^7.23.3 + "@babel/plugin-transform-async-generator-functions": ^7.23.4 + "@babel/plugin-transform-async-to-generator": ^7.23.3 + "@babel/plugin-transform-block-scoped-functions": ^7.23.3 + "@babel/plugin-transform-block-scoping": ^7.23.4 + "@babel/plugin-transform-class-properties": ^7.23.3 + "@babel/plugin-transform-class-static-block": ^7.23.4 + "@babel/plugin-transform-classes": ^7.23.5 + "@babel/plugin-transform-computed-properties": ^7.23.3 + "@babel/plugin-transform-destructuring": ^7.23.3 + "@babel/plugin-transform-dotall-regex": ^7.23.3 + "@babel/plugin-transform-duplicate-keys": ^7.23.3 + "@babel/plugin-transform-dynamic-import": ^7.23.4 + "@babel/plugin-transform-exponentiation-operator": ^7.23.3 + "@babel/plugin-transform-export-namespace-from": ^7.23.4 + "@babel/plugin-transform-for-of": ^7.23.3 + "@babel/plugin-transform-function-name": ^7.23.3 + "@babel/plugin-transform-json-strings": ^7.23.4 + "@babel/plugin-transform-literals": ^7.23.3 + "@babel/plugin-transform-logical-assignment-operators": ^7.23.4 + "@babel/plugin-transform-member-expression-literals": ^7.23.3 + "@babel/plugin-transform-modules-amd": ^7.23.3 + "@babel/plugin-transform-modules-commonjs": ^7.23.3 + "@babel/plugin-transform-modules-systemjs": ^7.23.3 + "@babel/plugin-transform-modules-umd": ^7.23.3 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.22.5 + "@babel/plugin-transform-new-target": ^7.23.3 + "@babel/plugin-transform-nullish-coalescing-operator": ^7.23.4 + "@babel/plugin-transform-numeric-separator": ^7.23.4 + "@babel/plugin-transform-object-rest-spread": ^7.23.4 + "@babel/plugin-transform-object-super": ^7.23.3 + "@babel/plugin-transform-optional-catch-binding": ^7.23.4 + "@babel/plugin-transform-optional-chaining": ^7.23.4 + "@babel/plugin-transform-parameters": ^7.23.3 + "@babel/plugin-transform-private-methods": ^7.23.3 + "@babel/plugin-transform-private-property-in-object": ^7.23.4 + "@babel/plugin-transform-property-literals": ^7.23.3 + "@babel/plugin-transform-regenerator": ^7.23.3 + "@babel/plugin-transform-reserved-words": ^7.23.3 + "@babel/plugin-transform-shorthand-properties": ^7.23.3 + "@babel/plugin-transform-spread": ^7.23.3 + "@babel/plugin-transform-sticky-regex": ^7.23.3 + "@babel/plugin-transform-template-literals": ^7.23.3 + "@babel/plugin-transform-typeof-symbol": ^7.23.3 + "@babel/plugin-transform-unicode-escapes": ^7.23.3 + "@babel/plugin-transform-unicode-property-regex": ^7.23.3 + "@babel/plugin-transform-unicode-regex": ^7.23.3 + "@babel/plugin-transform-unicode-sets-regex": ^7.23.3 + "@babel/preset-modules": 0.1.6-no-external-plugins + babel-plugin-polyfill-corejs2: ^0.4.6 + babel-plugin-polyfill-corejs3: ^0.8.5 + babel-plugin-polyfill-regenerator: ^0.5.3 + core-js-compat: ^3.31.0 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: adddd58d14fc1b2e5f8cf90995f522879362a0543e316afe9e5783f1bd715bb1e92300cd49d7ce3a95c64a96d60788d0089651e2cf4cac937f5469aac1087bb1 + languageName: node + linkType: hard + +"@babel/preset-env@npm:^7.20.2": + version: 7.25.4 + resolution: "@babel/preset-env@npm:7.25.4" + dependencies: + "@babel/compat-data": ^7.25.4 + "@babel/helper-compilation-targets": ^7.25.2 + "@babel/helper-plugin-utils": ^7.24.8 + "@babel/helper-validator-option": ^7.24.8 + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.25.3 + "@babel/plugin-bugfix-safari-class-field-initializer-scope": ^7.25.0 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.25.0 + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.24.7 + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.25.0 + "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/plugin-syntax-class-properties": ^7.12.13 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + "@babel/plugin-syntax-import-assertions": ^7.24.7 + "@babel/plugin-syntax-import-attributes": ^7.24.7 + "@babel/plugin-syntax-import-meta": ^7.10.4 + "@babel/plugin-syntax-json-strings": ^7.8.3 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + "@babel/plugin-syntax-top-level-await": ^7.14.5 + "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 + "@babel/plugin-transform-arrow-functions": ^7.24.7 + "@babel/plugin-transform-async-generator-functions": ^7.25.4 + "@babel/plugin-transform-async-to-generator": ^7.24.7 + "@babel/plugin-transform-block-scoped-functions": ^7.24.7 + "@babel/plugin-transform-block-scoping": ^7.25.0 + "@babel/plugin-transform-class-properties": ^7.25.4 + "@babel/plugin-transform-class-static-block": ^7.24.7 + "@babel/plugin-transform-classes": ^7.25.4 + "@babel/plugin-transform-computed-properties": ^7.24.7 + "@babel/plugin-transform-destructuring": ^7.24.8 + "@babel/plugin-transform-dotall-regex": ^7.24.7 + "@babel/plugin-transform-duplicate-keys": ^7.24.7 + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ^7.25.0 + "@babel/plugin-transform-dynamic-import": ^7.24.7 + "@babel/plugin-transform-exponentiation-operator": ^7.24.7 + "@babel/plugin-transform-export-namespace-from": ^7.24.7 + "@babel/plugin-transform-for-of": ^7.24.7 + "@babel/plugin-transform-function-name": ^7.25.1 + "@babel/plugin-transform-json-strings": ^7.24.7 + "@babel/plugin-transform-literals": ^7.25.2 + "@babel/plugin-transform-logical-assignment-operators": ^7.24.7 + "@babel/plugin-transform-member-expression-literals": ^7.24.7 + "@babel/plugin-transform-modules-amd": ^7.24.7 + "@babel/plugin-transform-modules-commonjs": ^7.24.8 + "@babel/plugin-transform-modules-systemjs": ^7.25.0 + "@babel/plugin-transform-modules-umd": ^7.24.7 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.24.7 + "@babel/plugin-transform-new-target": ^7.24.7 + "@babel/plugin-transform-nullish-coalescing-operator": ^7.24.7 + "@babel/plugin-transform-numeric-separator": ^7.24.7 + "@babel/plugin-transform-object-rest-spread": ^7.24.7 + "@babel/plugin-transform-object-super": ^7.24.7 + "@babel/plugin-transform-optional-catch-binding": ^7.24.7 + "@babel/plugin-transform-optional-chaining": ^7.24.8 + "@babel/plugin-transform-parameters": ^7.24.7 + "@babel/plugin-transform-private-methods": ^7.25.4 + "@babel/plugin-transform-private-property-in-object": ^7.24.7 + "@babel/plugin-transform-property-literals": ^7.24.7 + "@babel/plugin-transform-regenerator": ^7.24.7 + "@babel/plugin-transform-reserved-words": ^7.24.7 + "@babel/plugin-transform-shorthand-properties": ^7.24.7 + "@babel/plugin-transform-spread": ^7.24.7 + "@babel/plugin-transform-sticky-regex": ^7.24.7 + "@babel/plugin-transform-template-literals": ^7.24.7 + "@babel/plugin-transform-typeof-symbol": ^7.24.8 + "@babel/plugin-transform-unicode-escapes": ^7.24.7 + "@babel/plugin-transform-unicode-property-regex": ^7.24.7 + "@babel/plugin-transform-unicode-regex": ^7.24.7 + "@babel/plugin-transform-unicode-sets-regex": ^7.25.4 + "@babel/preset-modules": 0.1.6-no-external-plugins + babel-plugin-polyfill-corejs2: ^0.4.10 + babel-plugin-polyfill-corejs3: ^0.10.6 + babel-plugin-polyfill-regenerator: ^0.6.1 + core-js-compat: ^3.37.1 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 752be43f0b78a2eefe5007076aed3d21b505e1c09d134b61e7de8838f1bbb1e7af81023d39adb14b6eae23727fb5a9fd23f8115a44df043319be22319be17913 + languageName: node + linkType: hard + +"@babel/preset-modules@npm:0.1.6-no-external-plugins": + version: 0.1.6-no-external-plugins + resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" + dependencies: + "@babel/helper-plugin-utils": ^7.0.0 + "@babel/types": ^7.4.4 + esutils: ^2.0.2 + peerDependencies: + "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 + checksum: 4855e799bc50f2449fb5210f78ea9e8fd46cf4f242243f1e2ed838e2bd702e25e73e822e7f8447722a5f4baa5e67a8f7a0e403f3e7ce04540ff743a9c411c375 + languageName: node + linkType: hard + +"@babel/preset-react@npm:^7.18.6, @babel/preset-react@npm:^7.22.5": + version: 7.23.3 + resolution: "@babel/preset-react@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.15 + "@babel/plugin-transform-react-display-name": ^7.23.3 + "@babel/plugin-transform-react-jsx": ^7.22.15 + "@babel/plugin-transform-react-jsx-development": ^7.22.5 + "@babel/plugin-transform-react-pure-annotations": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2d90961e7e627a74b44551e88ad36a440579e283e8dc27972bf2f50682152bbc77228673a3ea22c0e0d005b70cbc487eccd64897c5e5e0384e5ce18f300b21eb + languageName: node + linkType: hard + +"@babel/preset-typescript@npm:^7.18.6, @babel/preset-typescript@npm:^7.22.5": + version: 7.23.3 + resolution: "@babel/preset-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.15 + "@babel/plugin-syntax-jsx": ^7.23.3 + "@babel/plugin-transform-modules-commonjs": ^7.23.3 + "@babel/plugin-transform-typescript": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 105a2d39bbc464da0f7e1ad7f535c77c5f62d6b410219355b20e552e7d29933567a5c55339b5d0aec1a5c7a0a7dfdf1b54aae601a4fe15a157d54dcbfcb3e854 + languageName: node + linkType: hard + +"@babel/preset-typescript@npm:^7.21.0": + version: 7.24.7 + resolution: "@babel/preset-typescript@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-validator-option": ^7.24.7 + "@babel/plugin-syntax-jsx": ^7.24.7 + "@babel/plugin-transform-modules-commonjs": ^7.24.7 + "@babel/plugin-transform-typescript": ^7.24.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 12929b24757f3bd6548103475f86478eda4c872bc7cefd920b29591eee8f4a4f350561d888e133d632d0c9402b8615fdcec9138e5127a6567dcb22f804ff207f + languageName: node + linkType: hard + +"@babel/regjsgen@npm:^0.8.0": + version: 0.8.0 + resolution: "@babel/regjsgen@npm:0.8.0" + checksum: 89c338fee774770e5a487382170711014d49a68eb281e74f2b5eac88f38300a4ad545516a7786a8dd5702e9cf009c94c2f582d200f077ac5decd74c56b973730 + languageName: node + linkType: hard + +"@babel/runtime-corejs3@npm:^7.18.6, @babel/runtime-corejs3@npm:^7.22.6": + version: 7.23.5 + resolution: "@babel/runtime-corejs3@npm:7.23.5" + dependencies: + core-js-pure: ^3.30.2 + regenerator-runtime: ^0.14.0 + checksum: 2798c77047d70f1483090aaa67ff5ea76c19687f15b5d7bc5e3772ea5c4ca4dc2d5fa3328ec94013981a627f50f5cb7c488972be415b832c1be76a20e13aa1e2 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.8.4": + version: 7.23.5 + resolution: "@babel/runtime@npm:7.23.5" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 164d9802424f06908e62d29b8fd3a87db55accf82f46f964ac481dcead11ff7df8391e3696e5fa91a8ca10ea8845bf650acd730fa88cf13f8026cd8d5eec6936 + languageName: node + linkType: hard + +"@babel/template@npm:^7.12.7, @babel/template@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/template@npm:7.22.15" + dependencies: + "@babel/code-frame": ^7.22.13 + "@babel/parser": ^7.22.15 + "@babel/types": ^7.22.15 + checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd + languageName: node + linkType: hard + +"@babel/template@npm:^7.24.7, @babel/template@npm:^7.25.0": + version: 7.25.0 + resolution: "@babel/template@npm:7.25.0" + dependencies: + "@babel/code-frame": ^7.24.7 + "@babel/parser": ^7.25.0 + "@babel/types": ^7.25.0 + checksum: 3f2db568718756d0daf2a16927b78f00c425046b654cd30b450006f2e84bdccaf0cbe6dc04994aa1f5f6a4398da2f11f3640a4d3ee31722e43539c4c919c817b + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.12.9, @babel/traverse@npm:^7.18.8, @babel/traverse@npm:^7.22.8, @babel/traverse@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/traverse@npm:7.23.5" + dependencies: + "@babel/code-frame": ^7.23.5 + "@babel/generator": ^7.23.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-hoist-variables": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/parser": ^7.23.5 + "@babel/types": ^7.23.5 + debug: ^4.1.0 + globals: ^11.1.0 + checksum: 0558b05360850c3ad6384e85bd55092126a8d5f93e29a8e227dd58fa1f9e1a4c25fd337c07c7ae509f0983e7a2b1e761ffdcfaa77a1e1bedbc867058e1de5a7d + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8, @babel/traverse@npm:^7.25.0, @babel/traverse@npm:^7.25.1, @babel/traverse@npm:^7.25.2, @babel/traverse@npm:^7.25.3, @babel/traverse@npm:^7.25.4": + version: 7.25.6 + resolution: "@babel/traverse@npm:7.25.6" + dependencies: + "@babel/code-frame": ^7.24.7 + "@babel/generator": ^7.25.6 + "@babel/parser": ^7.25.6 + "@babel/template": ^7.25.0 + "@babel/types": ^7.25.6 + debug: ^4.3.1 + globals: ^11.1.0 + checksum: 11ee47269aa4356f2d6633a05b9af73405b5ed72c09378daf644289b686ef852035a6ac9aa410f601991993c6bbf72006795b5478283b78eb1ca77874ada7737 + languageName: node + linkType: hard + +"@babel/types@npm:^7.12.7, @babel/types@npm:^7.20.0, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.23.5, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.23.5 + resolution: "@babel/types@npm:7.23.5" + dependencies: + "@babel/helper-string-parser": ^7.23.4 + "@babel/helper-validator-identifier": ^7.22.20 + to-fast-properties: ^2.0.0 + checksum: 3d21774480a459ef13b41c2e32700d927af649e04b70c5d164814d8e04ab584af66a93330602c2925e1a6925c2b829cc153418a613a4e7d79d011be1f29ad4b2 + languageName: node + linkType: hard + +"@babel/types@npm:^7.21.3, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.25.0, @babel/types@npm:^7.25.2, @babel/types@npm:^7.25.6": + version: 7.25.6 + resolution: "@babel/types@npm:7.25.6" + dependencies: + "@babel/helper-string-parser": ^7.24.8 + "@babel/helper-validator-identifier": ^7.24.7 + to-fast-properties: ^2.0.0 + checksum: 9b2f84ff3f874ad05b0b9bf06862c56f478b65781801f82296b4cc01bee39e79c20a7c0a06959fed0ee582c8267e1cb21638318655c5e070b0287242a844d1c9 + languageName: node + linkType: hard + +"@colors/colors@npm:1.5.0": + version: 1.5.0 + resolution: "@colors/colors@npm:1.5.0" + checksum: d64d5260bed1d5012ae3fc617d38d1afc0329fec05342f4e6b838f46998855ba56e0a73833f4a80fa8378c84810da254f76a8a19c39d038260dc06dc4e007425 + languageName: node + linkType: hard + +"@cspell/cspell-bundled-dicts@npm:8.3.2": + version: 8.3.2 + resolution: "@cspell/cspell-bundled-dicts@npm:8.3.2" + dependencies: + "@cspell/dict-ada": ^4.0.2 + "@cspell/dict-aws": ^4.0.1 + "@cspell/dict-bash": ^4.1.3 + "@cspell/dict-companies": ^3.0.29 + "@cspell/dict-cpp": ^5.0.10 + "@cspell/dict-cryptocurrencies": ^5.0.0 + "@cspell/dict-csharp": ^4.0.2 + "@cspell/dict-css": ^4.0.12 + "@cspell/dict-dart": ^2.0.3 + "@cspell/dict-django": ^4.1.0 + "@cspell/dict-docker": ^1.1.7 + "@cspell/dict-dotnet": ^5.0.0 + "@cspell/dict-elixir": ^4.0.3 + "@cspell/dict-en-common-misspellings": ^2.0.0 + "@cspell/dict-en-gb": 1.1.33 + "@cspell/dict-en_us": ^4.3.13 + "@cspell/dict-filetypes": ^3.0.3 + "@cspell/dict-fonts": ^4.0.0 + "@cspell/dict-fsharp": ^1.0.1 + "@cspell/dict-fullstack": ^3.1.5 + "@cspell/dict-gaming-terms": ^1.0.4 + "@cspell/dict-git": ^3.0.0 + "@cspell/dict-golang": ^6.0.5 + "@cspell/dict-haskell": ^4.0.1 + "@cspell/dict-html": ^4.0.5 + "@cspell/dict-html-symbol-entities": ^4.0.0 + "@cspell/dict-java": ^5.0.6 + "@cspell/dict-k8s": ^1.0.2 + "@cspell/dict-latex": ^4.0.0 + "@cspell/dict-lorem-ipsum": ^4.0.0 + "@cspell/dict-lua": ^4.0.3 + "@cspell/dict-makefile": ^1.0.0 + "@cspell/dict-node": ^4.0.3 + "@cspell/dict-npm": ^5.0.14 + "@cspell/dict-php": ^4.0.5 + "@cspell/dict-powershell": ^5.0.3 + "@cspell/dict-public-licenses": ^2.0.5 + "@cspell/dict-python": ^4.1.11 + "@cspell/dict-r": ^2.0.1 + "@cspell/dict-ruby": ^5.0.2 + "@cspell/dict-rust": ^4.0.1 + "@cspell/dict-scala": ^5.0.0 + "@cspell/dict-software-terms": ^3.3.15 + "@cspell/dict-sql": ^2.1.3 + "@cspell/dict-svelte": ^1.0.2 + "@cspell/dict-swift": ^2.0.1 + "@cspell/dict-typescript": ^3.1.2 + "@cspell/dict-vue": ^3.0.0 + checksum: 2b50d8a3d056a6e261e4d525fe8f70b8d4e9860c305f6ba21ea7869807b2b8100b30d6f4ff4da91ea0ac6fcea7191158c7091e839b3b41ee3052f3e3b401b347 + languageName: node + linkType: hard + +"@cspell/cspell-json-reporter@npm:8.3.2": + version: 8.3.2 + resolution: "@cspell/cspell-json-reporter@npm:8.3.2" + dependencies: + "@cspell/cspell-types": 8.3.2 + checksum: 25926f8cfef378dbce59f140d9f383db4598222a3de5f2a0a6840e225d694afce2c069498668304f4ec39e58f5570887ef0d31f45824ca16b0fc31f20180352e + languageName: node + linkType: hard + +"@cspell/cspell-pipe@npm:8.3.2": + version: 8.3.2 + resolution: "@cspell/cspell-pipe@npm:8.3.2" + checksum: 14b01d2cdc6af931a0b5ac9fcd5e5c358fcdd7710ed82d35a9dcf6c7d3e917bc5ac953571ec9fffa4ed22d8f872e2a74a10258cccac10b7cd49878c8c2e15a3c + languageName: node + linkType: hard + +"@cspell/cspell-resolver@npm:8.3.2": + version: 8.3.2 + resolution: "@cspell/cspell-resolver@npm:8.3.2" + dependencies: + global-directory: ^4.0.1 + checksum: fe723a1b8407b4168f6262cd30a97ad04eb5eb40f4cac3a11c6bf674ed67cc08525b0282b95edbcaf1d014dec3880f6f01b3f49e4319ade5b8e169f0a910f8d1 + languageName: node + linkType: hard + +"@cspell/cspell-service-bus@npm:8.3.2": + version: 8.3.2 + resolution: "@cspell/cspell-service-bus@npm:8.3.2" + checksum: 9bec7ddafcd8acab743248eb547fa5a84cf5363b0d0da354fdb2a0a6268a516b3600c7034ea71b6fca1c2517818f939876d961a4a3fc73a175eb62f5cbb6b7ae + languageName: node + linkType: hard + +"@cspell/cspell-types@npm:8.3.2": + version: 8.3.2 + resolution: "@cspell/cspell-types@npm:8.3.2" + checksum: 5f0b038e6717a3fa9c4109845c94e2a3d561a8b1a5dac073535929dee81e4d6d18af96759135a4dab6b06529a86ab1bd4e6b4a70121561bf22dfe4508140a5c3 + languageName: node + linkType: hard + +"@cspell/dict-ada@npm:^4.0.2": + version: 4.0.2 + resolution: "@cspell/dict-ada@npm:4.0.2" + checksum: 847729d40022db4df698aa9511c6b9073954f71268b64ad4fa354e6ac3eb5b03486bcb566ecadd4bccbebb4f188752eff2b2bdd9021b58dbf2cd61cd6a426752 + languageName: node + linkType: hard + +"@cspell/dict-aws@npm:^4.0.1": + version: 4.0.1 + resolution: "@cspell/dict-aws@npm:4.0.1" + checksum: 8445468151205fdfc51993ebc329e3a210a1628069971f973fb87c4d32cbb33676b32a370021efe0863ef63414632c8edf025ba7d296e932a93f3b05ba6193fc + languageName: node + linkType: hard + +"@cspell/dict-bash@npm:^4.1.3": + version: 4.1.3 + resolution: "@cspell/dict-bash@npm:4.1.3" + checksum: 4ba66c76c144d4c7ea1dd0fb92dfb0d7fd1e43a106a73fc7e9010b4a5c276aa4ef791c7161f56bf911356e3667ba043ee63271c1ffc485d9f8712553770e3ea9 + languageName: node + linkType: hard + +"@cspell/dict-companies@npm:^3.0.29": + version: 3.0.29 + resolution: "@cspell/dict-companies@npm:3.0.29" + checksum: ba2ee3fc7942ff932316038dc2a59b0edcf48321d9f31b75e1858637bd51be9b00bdafc2f3b70fa9d7e78cfbd016e08ef782cdf50bfc76b51e1bf22b1340e286 + languageName: node + linkType: hard + +"@cspell/dict-cpp@npm:^5.0.10": + version: 5.1.1 + resolution: "@cspell/dict-cpp@npm:5.1.1" + checksum: 2991434d97882c884ebef48d700ed80f1d0136b5dda9f97f49763874ba061103336fa97c07581ca73f23176030702778a93b43af49e73899f027c2b3263cdb6e + languageName: node + linkType: hard + +"@cspell/dict-cryptocurrencies@npm:^5.0.0": + version: 5.0.0 + resolution: "@cspell/dict-cryptocurrencies@npm:5.0.0" + checksum: 116e7f117b59ea4c9fa7ae1c3b47fc963e050448d43e059fb93731a256881ee262420edd5b9701ffe88af3d5e95b0337fc99b4dde1b0283ee0aaed45b23e281e + languageName: node + linkType: hard + +"@cspell/dict-csharp@npm:^4.0.2": + version: 4.0.2 + resolution: "@cspell/dict-csharp@npm:4.0.2" + checksum: d2ecb2aada51c5f0d6d557fd4f0c6eddb5b299e0955e066c49cd2afe96a1c6fe0afde699fdb885dd3183603a1efbd1d793b6a490b8d039256445b4b154b7375b + languageName: node + linkType: hard + +"@cspell/dict-css@npm:^4.0.12": + version: 4.0.12 + resolution: "@cspell/dict-css@npm:4.0.12" + checksum: 208c9434b8f5c8a33a96bb087572c10d5c946cd0847b9439271d0c4d2dcde5ee2588aca73bfea0c868d0124731b3ca890fab4762724d16435f161d4d5e7f3b9b + languageName: node + linkType: hard + +"@cspell/dict-dart@npm:^2.0.3": + version: 2.0.3 + resolution: "@cspell/dict-dart@npm:2.0.3" + checksum: 66bfcfa029baacd0b14b3ff5b6ab7597cf9459f77185d88b25123b42a4babb66df6786806843f1b6506c335326100599a2e1db6e6104e66bd021ede9ccb3cec4 + languageName: node + linkType: hard + +"@cspell/dict-data-science@npm:^1.0.11": + version: 1.0.11 + resolution: "@cspell/dict-data-science@npm:1.0.11" + checksum: 513f8f416f584f46576d45be23a4aa354e46d244f10a3d466222ffc13afe475e676639e4a24ab3a1ba157239f9ce23f7eef59c9f4c7a877a044db3a6344b18c6 + languageName: node + linkType: hard + +"@cspell/dict-django@npm:^4.1.0": + version: 4.1.0 + resolution: "@cspell/dict-django@npm:4.1.0" + checksum: b8a66135525e235bd6f2ea02de84ac7eae78e1068418f36b0c2260f9516b72492ef73f3fdc5fe8db2a6933747ff45a3eb743423a7dbf5b74548b1b1f30792679 + languageName: node + linkType: hard + +"@cspell/dict-docker@npm:^1.1.7": + version: 1.1.7 + resolution: "@cspell/dict-docker@npm:1.1.7" + checksum: 307f8b5132edca7cd291ba0ab6ed88f8787df984d6a42401b12a0da1ecb935d50af3a108ede885ce5bede96c445acdc88bb9ea8396de151c565a90a3bf66853e + languageName: node + linkType: hard + +"@cspell/dict-dotnet@npm:^5.0.0": + version: 5.0.0 + resolution: "@cspell/dict-dotnet@npm:5.0.0" + checksum: 3e55abd3cc0ecb0924caa245b83595c8e90b42a8fb438f3294d06ad32d30f3235dc8943a2865f06eaec5285a8d6a7df1db71fb228753d56a678a0f0cff87c24c + languageName: node + linkType: hard + +"@cspell/dict-elixir@npm:^4.0.3": + version: 4.0.3 + resolution: "@cspell/dict-elixir@npm:4.0.3" + checksum: f084449b2de5a2fa08076ac699c6073beaa4bb43796a662d681ea8fe5cba31f9efe718f3f98ef432ba75d4ea574316de34ab8422f79f4f2022cfddee7a7b8653 + languageName: node + linkType: hard + +"@cspell/dict-en-common-misspellings@npm:^2.0.0": + version: 2.0.0 + resolution: "@cspell/dict-en-common-misspellings@npm:2.0.0" + checksum: 977aac18d737d88e4cdca0771b664078a2d8cde1a0313696882581e67cb1acbf1f6a3923c1ee3f05878cfe3ad6f063a2e451f33e7df61cd1e0eb5de425bb4f2d + languageName: node + linkType: hard + +"@cspell/dict-en-gb@npm:1.1.33": + version: 1.1.33 + resolution: "@cspell/dict-en-gb@npm:1.1.33" + checksum: 09a9e7a3ee4cad75c87cc7adf6b5981b3ec52d4e3707e8de2e1a2a55cd5c8539057a7742d9c7035e23eb0aeff80a95b9599696c7192c9b3b9d8f14440fe01938 + languageName: node + linkType: hard + +"@cspell/dict-en_us@npm:^4.3.13": + version: 4.3.13 + resolution: "@cspell/dict-en_us@npm:4.3.13" + checksum: 4fc0d8458f3760a436956870742207214c73ae97da294117cae4fa8cf174b40dd6d237f8cb5d1bd4d8f82e3bfbd98cf885a9d79da1823f354d92a2724090a4f2 + languageName: node + linkType: hard + +"@cspell/dict-filetypes@npm:^3.0.3": + version: 3.0.3 + resolution: "@cspell/dict-filetypes@npm:3.0.3" + checksum: 22c38a0b2e98d6223b364ddb5948d14bf6427c8286d4ddb111d5da9bdd4c47ddc0c9199a575c314142da9aefcaa5777a4ea33ac07f239cb4b9b303e4bd888aa1 + languageName: node + linkType: hard + +"@cspell/dict-fonts@npm:^4.0.0": + version: 4.0.0 + resolution: "@cspell/dict-fonts@npm:4.0.0" + checksum: 7e33e4b39fb071165d81920dd0ccc07e4b737a7b09522acf3781b26136526e445e03e456caaecff261d76b711196b84cff7c21293853bf00ebe93f2e64c42520 + languageName: node + linkType: hard + +"@cspell/dict-fsharp@npm:^1.0.1": + version: 1.0.1 + resolution: "@cspell/dict-fsharp@npm:1.0.1" + checksum: ce0df20704bf95d1fe434d2889cc764279cbce2b057fc5247be1ccaf7a8cc57372de3da2cdab6643b3df5221119716929b2e2aaad3f60533dcf0bd3c7d892fab + languageName: node + linkType: hard + +"@cspell/dict-fullstack@npm:^3.1.5": + version: 3.1.5 + resolution: "@cspell/dict-fullstack@npm:3.1.5" + checksum: 01c98a3408d4bf4832f1f110252399e663ce869bb097d681558828bb0e22725c7fe7b43077aa57afc2c3158515eaa744074826c020825af5856a0950219785a6 + languageName: node + linkType: hard + +"@cspell/dict-gaming-terms@npm:^1.0.4": + version: 1.0.4 + resolution: "@cspell/dict-gaming-terms@npm:1.0.4" + checksum: 3e57f5567747a8598b3e4de4f63a3b8090cccf7688f3e91f0a9e005e916645db1224ea600afd5b497b7e8c6a1f9291dfd4cb932278dfd423657107203a2ace0b + languageName: node + linkType: hard + +"@cspell/dict-git@npm:^3.0.0": + version: 3.0.0 + resolution: "@cspell/dict-git@npm:3.0.0" + checksum: 97b6da58c93108bae0867515f790d84728f0bce580cc8ad6f0f5f63b2c81eaf6d084d543d99b693ff4d7fbea2413ff068c3e4811fc107820d243da2c06d381fa + languageName: node + linkType: hard + +"@cspell/dict-golang@npm:^6.0.5": + version: 6.0.5 + resolution: "@cspell/dict-golang@npm:6.0.5" + checksum: 20bf2c6a23d26f23e39629f3a48c31c2993d126b03ca31892e4e03ed48d2f5d5d929675987df54b6dad95828f6baa080111167e81a2dc3836c1f5b0b6db04a56 + languageName: node + linkType: hard + +"@cspell/dict-haskell@npm:^4.0.1": + version: 4.0.1 + resolution: "@cspell/dict-haskell@npm:4.0.1" + checksum: cfb51e415b60c5eb266a5782d0a4b19a37f1389b9b018d1bbb2ff4358bd739af1f76f68f26a138d4b4bd0ab67146d6eb9032fc3d3c212695237c134e05339c79 + languageName: node + linkType: hard + +"@cspell/dict-html-symbol-entities@npm:^4.0.0": + version: 4.0.0 + resolution: "@cspell/dict-html-symbol-entities@npm:4.0.0" + checksum: 79f05f9080f39dbde703980eb587ed6624b8fc2f5cedc297327bc1b9b7e6022a7c382e6013149b1afe00609b96003ab5c8d18d378979f76f336ab626317183f4 + languageName: node + linkType: hard + +"@cspell/dict-html@npm:^4.0.5": + version: 4.0.5 + resolution: "@cspell/dict-html@npm:4.0.5" + checksum: 2273e77cad6f373c4b0a43c5fb707725ff7c845e6de3545c8b05cbb2d82e1205f004a817498f561ced3d8d8b1d15848a82f2a667c0b64a1ee46cbde67d8ac136 + languageName: node + linkType: hard + +"@cspell/dict-java@npm:^5.0.6": + version: 5.0.6 + resolution: "@cspell/dict-java@npm:5.0.6" + checksum: 7d5df7831e8a4c0295ebbcfdf9a3185b197f1aa60ec85f7edf4aaec4cc1c53f37a291f3f95543642951d21ff487285f5cfb6e853b7f96f514a35052d59252909 + languageName: node + linkType: hard + +"@cspell/dict-k8s@npm:^1.0.2": + version: 1.0.2 + resolution: "@cspell/dict-k8s@npm:1.0.2" + checksum: 4afd7806033b2bf71b17f4cf3fbc33449492bfb2a33a8301cc97b2e55583c07a4a07c288f50f445261c1de4b95494e495b8b982ca428d285393f7eb917bb5a61 + languageName: node + linkType: hard + +"@cspell/dict-latex@npm:^4.0.0": + version: 4.0.0 + resolution: "@cspell/dict-latex@npm:4.0.0" + checksum: 33a3f158d8c0151cbb4e6bd79ba1189d167b3916e1ce37d7b5754d18dffefe061320fa54c3cb482bd5c7cf37392d0112530b07a3eca63dffbe1069de317dc652 + languageName: node + linkType: hard + +"@cspell/dict-lorem-ipsum@npm:^4.0.0": + version: 4.0.0 + resolution: "@cspell/dict-lorem-ipsum@npm:4.0.0" + checksum: d3575fb7b9684480192d2cd647484312c555f3d1215d6b35371b70de3ecde4273010e5916cc2d130ff1e1223a1a49f75825651671a76d3dabdec98acf67a3902 + languageName: node + linkType: hard + +"@cspell/dict-lua@npm:^4.0.3": + version: 4.0.3 + resolution: "@cspell/dict-lua@npm:4.0.3" + checksum: eee20135a4f0620302c5feeb50485f59af93c24b64eb2081a9e2096a106ce33ae565d6d92607582b44c9f17c8a091d82fbcb443ebae9b77f8512b0d66a703c3b + languageName: node + linkType: hard + +"@cspell/dict-makefile@npm:^1.0.0": + version: 1.0.0 + resolution: "@cspell/dict-makefile@npm:1.0.0" + checksum: f0cac4caf31e27accd5df5e0c2f53097cccbbd085126c4b4ecc08be2a32bd7f89fe6b052e9eae4ec99843175cafa94561868271fb53c5389f27cc078565b5123 + languageName: node + linkType: hard + +"@cspell/dict-node@npm:^4.0.3": + version: 4.0.3 + resolution: "@cspell/dict-node@npm:4.0.3" + checksum: 178e7f3ab45f30722cae7354803dd98ea6577c025a11eda9362fa795a06dd8e934f833bfc7d46816617974822ace11217505a1bd0ea2955aaee92cf94cc6b127 + languageName: node + linkType: hard + +"@cspell/dict-npm@npm:^5.0.14": + version: 5.0.14 + resolution: "@cspell/dict-npm@npm:5.0.14" + checksum: 791a23e8b6a726d77a9098f25b582e6a511be699f878526a036f9f0ec08ccf0c2082ec53a5ee056b59d3a22fe5f21e8e3d11e5c839a10e17cb919c8c71f74537 + languageName: node + linkType: hard + +"@cspell/dict-php@npm:^4.0.5": + version: 4.0.5 + resolution: "@cspell/dict-php@npm:4.0.5" + checksum: 017375f8a08f93872672b9d14c885b3114ea1b82cb8a4375029c7e71dcb303b82bf684fc84df3cbd8d74b9d1e74c80234280605ef8ca26a7972d99bbf15b14f9 + languageName: node + linkType: hard + +"@cspell/dict-powershell@npm:^5.0.3": + version: 5.0.3 + resolution: "@cspell/dict-powershell@npm:5.0.3" + checksum: 18eac3be8545b3df110bf867bd6285b11d7e67da037e00c9bc1376c5e322092bc1d925375a09df8b7420a6a35847aa20558610ffb491763eb82949f3af764e1d + languageName: node + linkType: hard + +"@cspell/dict-public-licenses@npm:^2.0.5": + version: 2.0.5 + resolution: "@cspell/dict-public-licenses@npm:2.0.5" + checksum: 07e647c24ed1a5f0e88828264581e9f8fde179f776a50c4389ac0bc5c09a2bb94280d299c94d1884a8da01fbf112c5640178789b457f06b1a97414b18cda99e0 + languageName: node + linkType: hard + +"@cspell/dict-python@npm:^4.1.11": + version: 4.1.11 + resolution: "@cspell/dict-python@npm:4.1.11" + dependencies: + "@cspell/dict-data-science": ^1.0.11 + checksum: cdfc493d3a260887dc31b115ab880849895522c4a0c0d4fe379a2e42ebf41f0724f02f778629e3e972fc6fa93e6d7bc7892e4b26b3b6fbf72399cf5d3b67585b + languageName: node + linkType: hard + +"@cspell/dict-r@npm:^2.0.1": + version: 2.0.1 + resolution: "@cspell/dict-r@npm:2.0.1" + checksum: fe85939ad4c8ada34284a673918be711cca60b6d6f1c48ee98602c27905228dfbaea3462a350094633032c1d6b6bba9548df7019e0b21673cf1cf887c57ca228 + languageName: node + linkType: hard + +"@cspell/dict-ruby@npm:^5.0.2": + version: 5.0.2 + resolution: "@cspell/dict-ruby@npm:5.0.2" + checksum: c2006bcc808448b1eef146eb4b6b74388113c50334206191a9fe5817fb13669482ecd114f7bbd397562ad2e19a9683266ff396f48c6ce282f6445c2cfa8e82c7 + languageName: node + linkType: hard + +"@cspell/dict-rust@npm:^4.0.1": + version: 4.0.1 + resolution: "@cspell/dict-rust@npm:4.0.1" + checksum: 146d3af5d0b1b84ec62059353416cd5d4b53995ed0a0edb47b96ed89f1b8b82881e76c1bac46311318f41d1619eab87d81e0cdc94855f50b79cfa0719333cbb1 + languageName: node + linkType: hard + +"@cspell/dict-scala@npm:^5.0.0": + version: 5.0.0 + resolution: "@cspell/dict-scala@npm:5.0.0" + checksum: 759dd8746e68e45299b65eeaf1dfd32d1e345fd80fd9a623af502266598c384198853001f70a700c454d8490fb9a5e1358ca1e0d7c0d43154a4f07e2d5531c72 + languageName: node + linkType: hard + +"@cspell/dict-software-terms@npm:^3.3.15": + version: 3.3.16 + resolution: "@cspell/dict-software-terms@npm:3.3.16" + checksum: 85ae16ecb3d4594da37d199113fdf3b77038cfe8d3b9dbaea248c597e484e45a9fcf42d4c234d4548911caace037f01d5f8442a787348dddea5777c8b023d441 + languageName: node + linkType: hard + +"@cspell/dict-sql@npm:^2.1.3": + version: 2.1.3 + resolution: "@cspell/dict-sql@npm:2.1.3" + checksum: a435812cc697d4c453f11efa49962992150702518e49808381ea34548b8a8ed81432a10cca36682007912b013c28e9ce3c6c183341c6cde58c8af0eef25cddc3 + languageName: node + linkType: hard + +"@cspell/dict-svelte@npm:^1.0.2": + version: 1.0.2 + resolution: "@cspell/dict-svelte@npm:1.0.2" + checksum: 5b42989bc6743a26ca5172cc23ebc1449d930695b10c908376048ce1835bf57fef7a0004f02ec5e43219f24a97f154e125041df470441199a045ed0be9e654fc + languageName: node + linkType: hard + +"@cspell/dict-swift@npm:^2.0.1": + version: 2.0.1 + resolution: "@cspell/dict-swift@npm:2.0.1" + checksum: 0bbb106266205c5f5e12886a73ebf0db2078bab1bdd2e1f304fe28445cd72d847a4c5072bf4fe8f9e8cdb4bc69d52fffec0806aea19ea9b64b7a87c67ee01175 + languageName: node + linkType: hard + +"@cspell/dict-typescript@npm:^3.1.2": + version: 3.1.2 + resolution: "@cspell/dict-typescript@npm:3.1.2" + checksum: 3cd0fa39856002975cf05b5584de42f58700a3420bd08b7b073af87dbcc1f66cab45e36a2156dd4e6c926cf67baaa192f02ccf61b9a9e5e94e69e035af54cec1 + languageName: node + linkType: hard + +"@cspell/dict-vue@npm:^3.0.0": + version: 3.0.0 + resolution: "@cspell/dict-vue@npm:3.0.0" + checksum: 4db58b1d6f9be1a523a35678877f2cca2bb04548b136ec5ec4e7186500978dbc32cc8747ced80ade3cad3acc3c80eb23afe980679165810f8f8f26802e952e2f + languageName: node + linkType: hard + +"@cspell/dynamic-import@npm:8.3.2": + version: 8.3.2 + resolution: "@cspell/dynamic-import@npm:8.3.2" + dependencies: + import-meta-resolve: ^4.0.0 + checksum: 176a5684922e9d3b3b277cdacbac14da509f691bd62da5135fab7c75db57f41c52ef0386c6ba3958e48dbc1b7b6f2751067c63bc1167ee09fae427c86dac71f7 + languageName: node + linkType: hard + +"@cspell/strong-weak-map@npm:8.3.2": + version: 8.3.2 + resolution: "@cspell/strong-weak-map@npm:8.3.2" + checksum: 696389c5ecb985bdded3530a088712ad03354051efc6506fae0328353a476604008a03364f3736de9041f51128b46ff6ffdda628c03c2c4800dc256a1b75e6ba + languageName: node + linkType: hard + +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" + dependencies: + "@jridgewell/trace-mapping": 0.3.9 + checksum: 5718f267085ed8edb3e7ef210137241775e607ee18b77d95aa5bd7514f47f5019aa2d82d96b3bf342ef7aa890a346fa1044532ff7cc3009e7d24fce3ce6200fa + languageName: node + linkType: hard + +"@discoveryjs/json-ext@npm:0.5.7, @discoveryjs/json-ext@npm:^0.5.0": + version: 0.5.7 + resolution: "@discoveryjs/json-ext@npm:0.5.7" + checksum: 2176d301cc258ea5c2324402997cf8134ebb212469c0d397591636cea8d3c02f2b3cf9fd58dcb748c7a0dade77ebdc1b10284fa63e608c033a1db52fddc69918 + languageName: node + linkType: hard + +"@docsearch/css@npm:3.5.2": + version: 3.5.2 + resolution: "@docsearch/css@npm:3.5.2" + checksum: d1d60dd230dd48f896755f21bd20b59583ba844212d7d336953ae48d389baaf868bdf83320fb734a4ed679c3f95b15d620cf3764cd538f6941cae239f8c9d35d + languageName: node + linkType: hard + +"@docsearch/react@npm:^3.5.2": + version: 3.5.2 + resolution: "@docsearch/react@npm:3.5.2" + dependencies: + "@algolia/autocomplete-core": 1.9.3 + "@algolia/autocomplete-preset-algolia": 1.9.3 + "@docsearch/css": 3.5.2 + algoliasearch: ^4.19.1 + peerDependencies: + "@types/react": ">= 16.8.0 < 19.0.0" + react: ">= 16.8.0 < 19.0.0" + react-dom: ">= 16.8.0 < 19.0.0" + search-insights: ">= 1 < 3" + peerDependenciesMeta: + "@types/react": + optional: true + react: + optional: true + react-dom: + optional: true + search-insights: + optional: true + checksum: 4b4584c2c73fc18cbd599047538896450974e134c2c74f19eb202db0ce8e6c3c49c6f65ed6ade61c796d476d3cbb55d6be58df62bc9568a0c72d88e42fca1d16 + languageName: node + linkType: hard + +"@docusaurus/core@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/core@npm:2.4.3" + dependencies: + "@babel/core": ^7.18.6 + "@babel/generator": ^7.18.7 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + "@babel/plugin-transform-runtime": ^7.18.6 + "@babel/preset-env": ^7.18.6 + "@babel/preset-react": ^7.18.6 + "@babel/preset-typescript": ^7.18.6 + "@babel/runtime": ^7.18.6 + "@babel/runtime-corejs3": ^7.18.6 + "@babel/traverse": ^7.18.8 + "@docusaurus/cssnano-preset": 2.4.3 + "@docusaurus/logger": 2.4.3 + "@docusaurus/mdx-loader": 2.4.3 + "@docusaurus/react-loadable": 5.5.2 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-common": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 + "@slorber/static-site-generator-webpack-plugin": ^4.0.7 + "@svgr/webpack": ^6.2.1 + autoprefixer: ^10.4.7 + babel-loader: ^8.2.5 + babel-plugin-dynamic-import-node: ^2.3.3 + boxen: ^6.2.1 + chalk: ^4.1.2 + chokidar: ^3.5.3 + clean-css: ^5.3.0 + cli-table3: ^0.6.2 + combine-promises: ^1.1.0 + commander: ^5.1.0 + copy-webpack-plugin: ^11.0.0 + core-js: ^3.23.3 + css-loader: ^6.7.1 + css-minimizer-webpack-plugin: ^4.0.0 + cssnano: ^5.1.12 + del: ^6.1.1 + detect-port: ^1.3.0 + escape-html: ^1.0.3 + eta: ^2.0.0 + file-loader: ^6.2.0 + fs-extra: ^10.1.0 + html-minifier-terser: ^6.1.0 + html-tags: ^3.2.0 + html-webpack-plugin: ^5.5.0 + import-fresh: ^3.3.0 + leven: ^3.1.0 + lodash: ^4.17.21 + mini-css-extract-plugin: ^2.6.1 + postcss: ^8.4.14 + postcss-loader: ^7.0.0 + prompts: ^2.4.2 + react-dev-utils: ^12.0.1 + react-helmet-async: ^1.3.0 + react-loadable: "npm:@docusaurus/react-loadable@5.5.2" + react-loadable-ssr-addon-v5-slorber: ^1.0.1 + react-router: ^5.3.3 + react-router-config: ^5.1.1 + react-router-dom: ^5.3.3 + rtl-detect: ^1.0.4 + semver: ^7.3.7 + serve-handler: ^6.1.3 + shelljs: ^0.8.5 + terser-webpack-plugin: ^5.3.3 + tslib: ^2.4.0 + update-notifier: ^5.1.0 + url-loader: ^4.1.1 + wait-on: ^6.0.1 + webpack: ^5.73.0 + webpack-bundle-analyzer: ^4.5.0 + webpack-dev-server: ^4.9.3 + webpack-merge: ^5.8.0 + webpackbar: ^5.0.2 + peerDependencies: + react: ^16.8.4 || ^17.0.0 + react-dom: ^16.8.4 || ^17.0.0 + bin: + docusaurus: bin/docusaurus.mjs + checksum: cce7173ee131364857c16f70f94155ba0e1b044cde54045fb0cf62ad138f8d8ef093f5aba7c7617a9aa0545b3ee3930aec2e09f645daec015696968338963013 + languageName: node + linkType: hard + +"@docusaurus/core@npm:3.5.2, @docusaurus/core@npm:^3.5.2": + version: 3.5.2 + resolution: "@docusaurus/core@npm:3.5.2" + dependencies: + "@babel/core": ^7.23.3 + "@babel/generator": ^7.23.3 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + "@babel/plugin-transform-runtime": ^7.22.9 + "@babel/preset-env": ^7.22.9 + "@babel/preset-react": ^7.22.5 + "@babel/preset-typescript": ^7.22.5 + "@babel/runtime": ^7.22.6 + "@babel/runtime-corejs3": ^7.22.6 + "@babel/traverse": ^7.22.8 + "@docusaurus/cssnano-preset": 3.5.2 + "@docusaurus/logger": 3.5.2 + "@docusaurus/mdx-loader": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-common": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + autoprefixer: ^10.4.14 + babel-loader: ^9.1.3 + babel-plugin-dynamic-import-node: ^2.3.3 + boxen: ^6.2.1 + chalk: ^4.1.2 + chokidar: ^3.5.3 + clean-css: ^5.3.2 + cli-table3: ^0.6.3 + combine-promises: ^1.1.0 + commander: ^5.1.0 + copy-webpack-plugin: ^11.0.0 + core-js: ^3.31.1 + css-loader: ^6.8.1 + css-minimizer-webpack-plugin: ^5.0.1 + cssnano: ^6.1.2 + del: ^6.1.1 + detect-port: ^1.5.1 + escape-html: ^1.0.3 + eta: ^2.2.0 + eval: ^0.1.8 + file-loader: ^6.2.0 + fs-extra: ^11.1.1 + html-minifier-terser: ^7.2.0 + html-tags: ^3.3.1 + html-webpack-plugin: ^5.5.3 + leven: ^3.1.0 + lodash: ^4.17.21 + mini-css-extract-plugin: ^2.7.6 + p-map: ^4.0.0 + postcss: ^8.4.26 + postcss-loader: ^7.3.3 + prompts: ^2.4.2 + react-dev-utils: ^12.0.1 + react-helmet-async: ^1.3.0 + react-loadable: "npm:@docusaurus/react-loadable@6.0.0" + react-loadable-ssr-addon-v5-slorber: ^1.0.1 + react-router: ^5.3.4 + react-router-config: ^5.1.1 + react-router-dom: ^5.3.4 + rtl-detect: ^1.0.4 + semver: ^7.5.4 + serve-handler: ^6.1.5 + shelljs: ^0.8.5 + terser-webpack-plugin: ^5.3.9 + tslib: ^2.6.0 + update-notifier: ^6.0.2 + url-loader: ^4.1.1 + webpack: ^5.88.1 + webpack-bundle-analyzer: ^4.9.0 + webpack-dev-server: ^4.15.1 + webpack-merge: ^5.9.0 + webpackbar: ^5.0.2 + peerDependencies: + "@mdx-js/react": ^3.0.0 + react: ^18.0.0 + react-dom: ^18.0.0 + bin: + docusaurus: bin/docusaurus.mjs + checksum: 6c6282a75931f0f8f8f8768232b4436ff8679ae12b619f7bd01e0d83aa346e24ab0d9cecac034f9dc95c55059997efdd963d052d3e429583bfb8d3b54ab750d3 + languageName: node + linkType: hard + +"@docusaurus/cssnano-preset@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/cssnano-preset@npm:2.4.3" + dependencies: + cssnano-preset-advanced: ^5.3.8 + postcss: ^8.4.14 + postcss-sort-media-queries: ^4.2.1 + tslib: ^2.4.0 + checksum: f4a4c60b075c23541da90e00ae26af2e7eaadf20d783b37b9110a5e34599e4e91947425e33bad58ba71abee81c85cca99f5d7d76575f53fbaf73617b55e39c62 + languageName: node + linkType: hard + +"@docusaurus/cssnano-preset@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/cssnano-preset@npm:3.5.2" + dependencies: + cssnano-preset-advanced: ^6.1.2 + postcss: ^8.4.38 + postcss-sort-media-queries: ^5.2.0 + tslib: ^2.6.0 + checksum: 4bb1fae3741e14cbbdb64c1b0707435970838bf219831234a70cf382e6811ffac1cadf733d5e1fe7c278e7b2a9e533bfa802a5212b22ec46edd703208cf49f92 + languageName: node + linkType: hard + +"@docusaurus/logger@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/logger@npm:2.4.3" + dependencies: + chalk: ^4.1.2 + tslib: ^2.4.0 + checksum: f026a8233aa317f16ce5b25c6785a431f319c52fc07a1b9e26f4b3df2197974e75830a16b6140314f8f4ef02dc19242106ec2ae1599740b26d516cc34c56102f + languageName: node + linkType: hard + +"@docusaurus/logger@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/logger@npm:3.5.2" + dependencies: + chalk: ^4.1.2 + tslib: ^2.6.0 + checksum: 7cbdcf54acd6e7787ca5a10b9c884be4b9e8fdae837862c66550a0bf3d02737f72c3188b2bddd61da6d8530eb2eb2b646ea599a79416e33c4998f1a87d2f6a8c + languageName: node + linkType: hard + +"@docusaurus/mdx-loader@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/mdx-loader@npm:2.4.3" + dependencies: + "@babel/parser": ^7.18.8 + "@babel/traverse": ^7.18.8 + "@docusaurus/logger": 2.4.3 + "@docusaurus/utils": 2.4.3 + "@mdx-js/mdx": ^1.6.22 + escape-html: ^1.0.3 + file-loader: ^6.2.0 + fs-extra: ^10.1.0 + image-size: ^1.0.1 + mdast-util-to-string: ^2.0.0 + remark-emoji: ^2.2.0 + stringify-object: ^3.3.0 + tslib: ^2.4.0 + unified: ^9.2.2 + unist-util-visit: ^2.0.3 + url-loader: ^4.1.1 + webpack: ^5.73.0 + peerDependencies: + react: ^16.8.4 || ^17.0.0 + react-dom: ^16.8.4 || ^17.0.0 + checksum: 5a774f7ea5f484e888b2bd1bf8b182279e3788afec779eb8920cf468b92ab8d83a1ae8be51925074241a4d1a38d989cfb366d2baf0f67ed6f063342395a7ca8e + languageName: node + linkType: hard + +"@docusaurus/mdx-loader@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/mdx-loader@npm:3.5.2" + dependencies: + "@docusaurus/logger": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + "@mdx-js/mdx": ^3.0.0 + "@slorber/remark-comment": ^1.0.0 + escape-html: ^1.0.3 + estree-util-value-to-estree: ^3.0.1 + file-loader: ^6.2.0 + fs-extra: ^11.1.1 + image-size: ^1.0.2 + mdast-util-mdx: ^3.0.0 + mdast-util-to-string: ^4.0.0 + rehype-raw: ^7.0.0 + remark-directive: ^3.0.0 + remark-emoji: ^4.0.0 + remark-frontmatter: ^5.0.0 + remark-gfm: ^4.0.0 + stringify-object: ^3.3.0 + tslib: ^2.6.0 + unified: ^11.0.3 + unist-util-visit: ^5.0.0 + url-loader: ^4.1.1 + vfile: ^6.0.1 + webpack: ^5.88.1 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 36186c2f3487631757b24ba3a21575d2253ca1e6ada82d556bf323da7ae7637c0880eb388bf375e207bc5f26dcd8b58cc76d763e6c2caf6ed80f88748444ce8d + languageName: node + linkType: hard + +"@docusaurus/module-type-aliases@npm:2.4.3": + version: 2.4.3 + resolution: "@docusaurus/module-type-aliases@npm:2.4.3" + dependencies: + "@docusaurus/react-loadable": 5.5.2 + "@docusaurus/types": 2.4.3 + "@types/history": ^4.7.11 + "@types/react": "*" + "@types/react-router-config": "*" + "@types/react-router-dom": "*" + react-helmet-async: "*" + react-loadable: "npm:@docusaurus/react-loadable@5.5.2" + peerDependencies: + react: "*" + react-dom: "*" + checksum: 22ce1a6a20acc35cdd2ec57e55f29e65dbe0fb3a46aaa8c033ec78bf04cd3087f0523c816c744ed311095512dd686c83e0a8619cc1a2a937c27cd54527739c38 + languageName: node + linkType: hard + +"@docusaurus/module-type-aliases@npm:3.5.2, @docusaurus/module-type-aliases@npm:^3.5.2": + version: 3.5.2 + resolution: "@docusaurus/module-type-aliases@npm:3.5.2" + dependencies: + "@docusaurus/types": 3.5.2 + "@types/history": ^4.7.11 + "@types/react": "*" + "@types/react-router-config": "*" + "@types/react-router-dom": "*" + react-helmet-async: "*" + react-loadable: "npm:@docusaurus/react-loadable@6.0.0" + peerDependencies: + react: "*" + react-dom: "*" + checksum: 0161db859d459bb25ac162f0c509fb1316dfb403a9e89f325a9bc7d9f35ae1825b9703a435777903ba93de827d4413b189bbd0c03018ac13d66b50633302ea80 + languageName: node + linkType: hard + +"@docusaurus/plugin-content-blog@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/plugin-content-blog@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/logger": 3.5.2 + "@docusaurus/mdx-loader": 3.5.2 + "@docusaurus/theme-common": 3.5.2 + "@docusaurus/types": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-common": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + cheerio: 1.0.0-rc.12 + feed: ^4.2.2 + fs-extra: ^11.1.1 + lodash: ^4.17.21 + reading-time: ^1.5.0 + srcset: ^4.0.0 + tslib: ^2.6.0 + unist-util-visit: ^5.0.0 + utility-types: ^3.10.0 + webpack: ^5.88.1 + peerDependencies: + "@docusaurus/plugin-content-docs": "*" + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: c5997b9d86ccf939998f9d56e65491ecf9e677d8425e95a79b3b428041d4dfc4ecb03a18ef595777c3ad5bd65f4a2dd30d99cb6f1b411161bf7cd32027ecc6d5 + languageName: node + linkType: hard + +"@docusaurus/plugin-content-docs@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/plugin-content-docs@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/logger": 3.5.2 + "@docusaurus/mdx-loader": 3.5.2 + "@docusaurus/module-type-aliases": 3.5.2 + "@docusaurus/theme-common": 3.5.2 + "@docusaurus/types": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-common": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + "@types/react-router-config": ^5.0.7 + combine-promises: ^1.1.0 + fs-extra: ^11.1.1 + js-yaml: ^4.1.0 + lodash: ^4.17.21 + tslib: ^2.6.0 + utility-types: ^3.10.0 + webpack: ^5.88.1 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: fb7ba7f8a6741b14bbe8db0bf1b12ff7a24d12c40d8276f32b9b393881d74bfed3bed4f1e5b0756cac0e43c4bd8106094d5cf6a3c527400e9713283fc3832dab + languageName: node + linkType: hard + +"@docusaurus/plugin-content-docs@npm:^2.0.0-rc.1": + version: 2.4.3 + resolution: "@docusaurus/plugin-content-docs@npm:2.4.3" + dependencies: + "@docusaurus/core": 2.4.3 + "@docusaurus/logger": 2.4.3 + "@docusaurus/mdx-loader": 2.4.3 + "@docusaurus/module-type-aliases": 2.4.3 + "@docusaurus/types": 2.4.3 + "@docusaurus/utils": 2.4.3 + "@docusaurus/utils-validation": 2.4.3 + "@types/react-router-config": ^5.0.6 + combine-promises: ^1.1.0 + fs-extra: ^10.1.0 + import-fresh: ^3.3.0 + js-yaml: ^4.1.0 + lodash: ^4.17.21 + tslib: ^2.4.0 + utility-types: ^3.10.0 + webpack: ^5.73.0 + peerDependencies: + react: ^16.8.4 || ^17.0.0 + react-dom: ^16.8.4 || ^17.0.0 + checksum: bc01201f64721131eb84f264e51c7497b8034d2a3d99d762169f5dc456c3d8882acfa01fdbaa8fdc6e2e220479b36e0c9e8e17397bf887884589535bdeaeb4bb + languageName: node + linkType: hard + +"@docusaurus/plugin-content-pages@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/plugin-content-pages@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/mdx-loader": 3.5.2 + "@docusaurus/types": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + fs-extra: ^11.1.1 + tslib: ^2.6.0 + webpack: ^5.88.1 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 8b3f1040e8ec006c9431508e73ef3f61cd5759bece3770189f7d52609f91bd156c9b18d0608f9cb14c456a1d1823be6633c573d5eee7cf9bd142b0f978c7a745 + languageName: node + linkType: hard + +"@docusaurus/plugin-debug@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/plugin-debug@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/types": 3.5.2 + "@docusaurus/utils": 3.5.2 + fs-extra: ^11.1.1 + react-json-view-lite: ^1.2.0 + tslib: ^2.6.0 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: a839e6c3a595ea202fdd7fbce638ab8df26ba73a8c7ead8c04d1bbb509ebe34e9633e7fe9eb54a7a733e93a03d74a60df4d9f6597b9621ff464280d4dd71db34 + languageName: node + linkType: hard + +"@docusaurus/plugin-google-analytics@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/plugin-google-analytics@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/types": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + tslib: ^2.6.0 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 0b8c4d21333d40c2509d6ef807caaf69f085010c5deac514ab34f53b5486fd76766c90213dc98976a6c4d66fdfa14bf6b05594e51e8a53ec60c2a3fa08fd9a83 + languageName: node + linkType: hard + +"@docusaurus/plugin-google-gtag@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/plugin-google-gtag@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/types": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + "@types/gtag.js": ^0.0.12 + tslib: ^2.6.0 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 5d53c2483c8c7e3a8e842bd091a774d4041f0e165d216b3c02f031a224a77258c9456e8b2acd0500b4a0eff474a83c1b82803628db9d4b132514409936c68ac4 + languageName: node + linkType: hard + +"@docusaurus/plugin-google-tag-manager@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/plugin-google-tag-manager@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/types": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + tslib: ^2.6.0 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 9a6fc2ca54ea677c6edfd78f4f392d7d9ae86afd085fcda96d5ac41efa441352c25a2519595d9d15fb9b838e2ae39837f0daf02e2406c5cd56199ae237bd7b7a + languageName: node + linkType: hard + +"@docusaurus/plugin-sitemap@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/plugin-sitemap@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/logger": 3.5.2 + "@docusaurus/types": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-common": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + fs-extra: ^11.1.1 + sitemap: ^7.1.1 + tslib: ^2.6.0 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 26b6bceb7ab87fe7f6f666742d1e81de32cdacc5aaa3d45d91002c7d64e3258f3d0aac87c6b0d442eaf34ede2af4b7521b50737f2e8e2718daff6fce10230213 + languageName: node + linkType: hard + +"@docusaurus/preset-classic@npm:^3.5.2": + version: 3.5.2 + resolution: "@docusaurus/preset-classic@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/plugin-content-blog": 3.5.2 + "@docusaurus/plugin-content-docs": 3.5.2 + "@docusaurus/plugin-content-pages": 3.5.2 + "@docusaurus/plugin-debug": 3.5.2 + "@docusaurus/plugin-google-analytics": 3.5.2 + "@docusaurus/plugin-google-gtag": 3.5.2 + "@docusaurus/plugin-google-tag-manager": 3.5.2 + "@docusaurus/plugin-sitemap": 3.5.2 + "@docusaurus/theme-classic": 3.5.2 + "@docusaurus/theme-common": 3.5.2 + "@docusaurus/theme-search-algolia": 3.5.2 + "@docusaurus/types": 3.5.2 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: ec578e62b3b13b1874b14235a448a913c2d2358ea9b9d9c60bb250be468ab62387c88ec44e1ee82ad5b3d7243306e31919888a80eae62e5e8eab0ae12194bf69 + languageName: node + linkType: hard + +"@docusaurus/react-loadable@npm:5.5.2, react-loadable@npm:@docusaurus/react-loadable@5.5.2": + version: 5.5.2 + resolution: "@docusaurus/react-loadable@npm:5.5.2" + dependencies: + "@types/react": "*" + prop-types: ^15.6.2 + peerDependencies: + react: "*" + checksum: 930fb9e2936412a12461f210acdc154a433283921ca43ac3fc3b84cb6c12eb738b3a3719373022bf68004efeb1a928dbe36c467d7a1f86454ed6241576d936e7 + languageName: node + linkType: hard + +"@docusaurus/theme-classic@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/theme-classic@npm:3.5.2" + dependencies: + "@docusaurus/core": 3.5.2 + "@docusaurus/mdx-loader": 3.5.2 + "@docusaurus/module-type-aliases": 3.5.2 + "@docusaurus/plugin-content-blog": 3.5.2 + "@docusaurus/plugin-content-docs": 3.5.2 + "@docusaurus/plugin-content-pages": 3.5.2 + "@docusaurus/theme-common": 3.5.2 + "@docusaurus/theme-translations": 3.5.2 + "@docusaurus/types": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-common": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + "@mdx-js/react": ^3.0.0 + clsx: ^2.0.0 + copy-text-to-clipboard: ^3.2.0 + infima: 0.2.0-alpha.44 + lodash: ^4.17.21 + nprogress: ^0.2.0 + postcss: ^8.4.26 + prism-react-renderer: ^2.3.0 + prismjs: ^1.29.0 + react-router-dom: ^5.3.4 + rtlcss: ^4.1.0 + tslib: ^2.6.0 + utility-types: ^3.10.0 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 6c415b01ad24bb43eb166e2b780a84356ff14a627627f6a541c2803832d56c4f9409a5636048693d2d24804f59c2cc7bda925d9ef999a8276fe125477d2b2e1e + languageName: node + linkType: hard + +"@docusaurus/theme-common@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/theme-common@npm:3.5.2" + dependencies: + "@docusaurus/mdx-loader": 3.5.2 + "@docusaurus/module-type-aliases": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-common": 3.5.2 + "@types/history": ^4.7.11 + "@types/react": "*" + "@types/react-router-config": "*" + clsx: ^2.0.0 + parse-numeric-range: ^1.3.0 + prism-react-renderer: ^2.3.0 + tslib: ^2.6.0 + utility-types: ^3.10.0 + peerDependencies: + "@docusaurus/plugin-content-docs": "*" + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: c78ec7f6035abc920a2a0bc1ad78920178a5452538a3a70794eca8d4b976725f6ccc464ee3092afd31ca59b4e061ad4c21cdce7f5e10b06567075814b2fc2002 + languageName: node + linkType: hard + +"@docusaurus/theme-search-algolia@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/theme-search-algolia@npm:3.5.2" + dependencies: + "@docsearch/react": ^3.5.2 + "@docusaurus/core": 3.5.2 + "@docusaurus/logger": 3.5.2 + "@docusaurus/plugin-content-docs": 3.5.2 + "@docusaurus/theme-common": 3.5.2 + "@docusaurus/theme-translations": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-validation": 3.5.2 + algoliasearch: ^4.18.0 + algoliasearch-helper: ^3.13.3 + clsx: ^2.0.0 + eta: ^2.2.0 + fs-extra: ^11.1.1 + lodash: ^4.17.21 + tslib: ^2.6.0 + utility-types: ^3.10.0 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: e945e3001996477597bfad074eaef074cf4c5365ed3076c3109130a2252b266e4e2fac46904a0626eedeff23b9ac11e7b985cc71f5485ede52d3ddf379b7959b + languageName: node + linkType: hard + +"@docusaurus/theme-translations@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/theme-translations@npm:3.5.2" + dependencies: + fs-extra: ^11.1.1 + tslib: ^2.6.0 + checksum: dc523c74a13fb8552c03e547c6de1c21881d899cc74bf088a2bed716e0ef1a4ceba2726c43656d87fff60413ca191f5ea946b182e4ae4129c14da832b5194d82 + languageName: node + linkType: hard + +"@docusaurus/theme-translations@npm:^2.0.0-rc.1": + version: 2.4.3 + resolution: "@docusaurus/theme-translations@npm:2.4.3" + dependencies: + fs-extra: ^10.1.0 + tslib: ^2.4.0 + checksum: 8424583a130b0d32b6adf578dc5daeefaad199019c8a6a23fbd67577209be64923cde59d423ea9d41d6e7cfc2318e7fa6a17a665e8ae1c871ce0880525f9b8fd + languageName: node + linkType: hard + +"@docusaurus/tsconfig@npm:^3.5.2": + version: 3.5.2 + resolution: "@docusaurus/tsconfig@npm:3.5.2" + checksum: 808a17eaf422ae9a948c6558dd1e92d4700b067ead3a63a84049c6845bf94f84e311cd0e4d517047fe9ea057efe393bb22c2d5c92d727d06c9f895e971f2c3ea + languageName: node + linkType: hard + +"@docusaurus/types@npm:2.4.3, @docusaurus/types@npm:^2.4.1": + version: 2.4.3 + resolution: "@docusaurus/types@npm:2.4.3" + dependencies: + "@types/history": ^4.7.11 + "@types/react": "*" + commander: ^5.1.0 + joi: ^17.6.0 + react-helmet-async: ^1.3.0 + utility-types: ^3.10.0 + webpack: ^5.73.0 + webpack-merge: ^5.8.0 + peerDependencies: + react: ^16.8.4 || ^17.0.0 + react-dom: ^16.8.4 || ^17.0.0 + checksum: c123c45630e885b588f808baa06a97f8408a3381906f65cb92ae75732aedfca6ab2cada94f969c08e043b885b95298616440326259b789010e0986cbcd7a960b + languageName: node + linkType: hard + +"@docusaurus/types@npm:3.5.2, @docusaurus/types@npm:^3.5.2": + version: 3.5.2 + resolution: "@docusaurus/types@npm:3.5.2" + dependencies: + "@mdx-js/mdx": ^3.0.0 + "@types/history": ^4.7.11 + "@types/react": "*" + commander: ^5.1.0 + joi: ^17.9.2 + react-helmet-async: ^1.3.0 + utility-types: ^3.10.0 + webpack: ^5.88.1 + webpack-merge: ^5.9.0 + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: e39451b7b08673ad5e1551ee6e4286f90f2554cf9ba245abfa56670550f48afca9c57b01c10ffa21dacb734c0fcd067150eeb2b1c1ebb1692f1f538b1eed0029 + languageName: node + linkType: hard + +"@docusaurus/utils-common@npm:2.4.3, @docusaurus/utils-common@npm:^2.0.0-rc.1": + version: 2.4.3 + resolution: "@docusaurus/utils-common@npm:2.4.3" + dependencies: + tslib: ^2.4.0 + peerDependencies: + "@docusaurus/types": "*" + peerDependenciesMeta: + "@docusaurus/types": + optional: true + checksum: 1ae315d8d8ce7a0163a698ffdca55b734d21f336512138c128bc0fa2a8d224edbaad0c8dbd7a3de2e8ef734dc2656c505d09066dee4fc84819d153593abb8984 + languageName: node + linkType: hard + +"@docusaurus/utils-common@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/utils-common@npm:3.5.2" + dependencies: + tslib: ^2.6.0 + peerDependencies: + "@docusaurus/types": "*" + peerDependenciesMeta: + "@docusaurus/types": + optional: true + checksum: 9d550c89663d4271456ae0832c82a1691207ccc95e21df3a05a4bd6bbd2624bb9e3ab7327d939c04b2023378987bcf99321b2c37be1af214852832f65d6db14a + languageName: node + linkType: hard + +"@docusaurus/utils-validation@npm:2.4.3, @docusaurus/utils-validation@npm:^2.0.0-rc.1": + version: 2.4.3 + resolution: "@docusaurus/utils-validation@npm:2.4.3" + dependencies: + "@docusaurus/logger": 2.4.3 + "@docusaurus/utils": 2.4.3 + joi: ^17.6.0 + js-yaml: ^4.1.0 + tslib: ^2.4.0 + checksum: d3472b3f7a0a029c2cef1f00bc9db403d5f7e74e2091eccbc45d06f5776a84fd73bd1a18cf3a8a3cc0348ce49f753a1300deac670c2a82c56070cc40ca9df06e + languageName: node + linkType: hard + +"@docusaurus/utils-validation@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/utils-validation@npm:3.5.2" + dependencies: + "@docusaurus/logger": 3.5.2 + "@docusaurus/utils": 3.5.2 + "@docusaurus/utils-common": 3.5.2 + fs-extra: ^11.2.0 + joi: ^17.9.2 + js-yaml: ^4.1.0 + lodash: ^4.17.21 + tslib: ^2.6.0 + checksum: 5966e6d0e8f26292c629899f13b545501b53b345b0e2291bb47aaa80d7c9c5cf155e15a4ecd073a4095ee7c83c6db3612e0a34f81a8187fd20410b1aeb92d731 + languageName: node + linkType: hard + +"@docusaurus/utils@npm:2.4.3, @docusaurus/utils@npm:^2.0.0-rc.1": + version: 2.4.3 + resolution: "@docusaurus/utils@npm:2.4.3" + dependencies: + "@docusaurus/logger": 2.4.3 + "@svgr/webpack": ^6.2.1 + escape-string-regexp: ^4.0.0 + file-loader: ^6.2.0 + fs-extra: ^10.1.0 + github-slugger: ^1.4.0 + globby: ^11.1.0 + gray-matter: ^4.0.3 + js-yaml: ^4.1.0 + lodash: ^4.17.21 + micromatch: ^4.0.5 + resolve-pathname: ^3.0.0 + shelljs: ^0.8.5 + tslib: ^2.4.0 + url-loader: ^4.1.1 + webpack: ^5.73.0 + peerDependencies: + "@docusaurus/types": "*" + peerDependenciesMeta: + "@docusaurus/types": + optional: true + checksum: dd1aa7688d1a4b2775e13a91d528608ceab33c57a921404d9a989867c31c8ef17fe3892e4f5680dfb4a783da7b9973e2077e907ff4ac172927433e606e8fa9b9 + languageName: node + linkType: hard + +"@docusaurus/utils@npm:3.5.2": + version: 3.5.2 + resolution: "@docusaurus/utils@npm:3.5.2" + dependencies: + "@docusaurus/logger": 3.5.2 + "@docusaurus/utils-common": 3.5.2 + "@svgr/webpack": ^8.1.0 + escape-string-regexp: ^4.0.0 + file-loader: ^6.2.0 + fs-extra: ^11.1.1 + github-slugger: ^1.5.0 + globby: ^11.1.0 + gray-matter: ^4.0.3 + jiti: ^1.20.0 + js-yaml: ^4.1.0 + lodash: ^4.17.21 + micromatch: ^4.0.5 + prompts: ^2.4.2 + resolve-pathname: ^3.0.0 + shelljs: ^0.8.5 + tslib: ^2.6.0 + url-loader: ^4.1.1 + utility-types: ^3.10.0 + webpack: ^5.88.1 + peerDependencies: + "@docusaurus/types": "*" + peerDependenciesMeta: + "@docusaurus/types": + optional: true + checksum: 0e0f4fc65ed076d4e4b551ecb61447b7c2468060d1655afff314515844ae34dc0546f467f53bff535f3144afc109e974da27fadb7c678a5d19966bed9e7a27c4 + languageName: node + linkType: hard + +"@easyops-cn/autocomplete.js@npm:^0.38.1": + version: 0.38.1 + resolution: "@easyops-cn/autocomplete.js@npm:0.38.1" + dependencies: + cssesc: ^3.0.0 + immediate: ^3.2.3 + checksum: d88b61f12c383856b8d5cedf176a6d07a21e013dc2c78be029af81e2e026ece2bb988c6ea7f9951a2759c2e6f806ea1d1c9627bf36d9cbe376e897a94ce5da09 + languageName: node + linkType: hard + +"@easyops-cn/docusaurus-search-local@npm:^0.35.0": + version: 0.35.0 + resolution: "@easyops-cn/docusaurus-search-local@npm:0.35.0" + dependencies: + "@docusaurus/plugin-content-docs": ^2.0.0-rc.1 + "@docusaurus/theme-translations": ^2.0.0-rc.1 + "@docusaurus/utils": ^2.0.0-rc.1 + "@docusaurus/utils-common": ^2.0.0-rc.1 + "@docusaurus/utils-validation": ^2.0.0-rc.1 + "@easyops-cn/autocomplete.js": ^0.38.1 + "@node-rs/jieba": ^1.6.0 + cheerio: ^1.0.0-rc.3 + clsx: ^1.1.1 + debug: ^4.2.0 + fs-extra: ^10.0.0 + klaw-sync: ^6.0.0 + lunr: ^2.3.9 + lunr-languages: ^1.4.0 + mark.js: ^8.11.1 + tslib: ^2.4.0 + peerDependencies: + "@docusaurus/theme-common": ^2.0.0-rc.1 + react: ^16.14.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0 + checksum: 726b7b5d52f3fd01286e5a97bb2f5d27ae0ace2be7a7742c92b0bf11d56f2f44a16f6b7af556f5676ffa2a3b94c244d17ea9804894553f94ba66b98249e1e10f + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-arm64@npm:0.17.19" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/android-arm64@npm:0.18.20" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-arm@npm:0.17.19" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/android-arm@npm:0.18.20" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-x64@npm:0.17.19" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/android-x64@npm:0.18.20" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/darwin-arm64@npm:0.17.19" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/darwin-arm64@npm:0.18.20" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/darwin-x64@npm:0.17.19" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/darwin-x64@npm:0.18.20" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/freebsd-arm64@npm:0.17.19" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/freebsd-arm64@npm:0.18.20" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/freebsd-x64@npm:0.17.19" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/freebsd-x64@npm:0.18.20" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-arm64@npm:0.17.19" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-arm64@npm:0.18.20" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-arm@npm:0.17.19" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-arm@npm:0.18.20" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-ia32@npm:0.17.19" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-ia32@npm:0.18.20" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-loong64@npm:0.17.19" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-loong64@npm:0.18.20" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-mips64el@npm:0.17.19" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-mips64el@npm:0.18.20" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-ppc64@npm:0.17.19" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-ppc64@npm:0.18.20" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-riscv64@npm:0.17.19" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-riscv64@npm:0.18.20" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-s390x@npm:0.17.19" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-s390x@npm:0.18.20" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-x64@npm:0.17.19" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-x64@npm:0.18.20" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/netbsd-x64@npm:0.17.19" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/netbsd-x64@npm:0.18.20" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/openbsd-x64@npm:0.17.19" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/openbsd-x64@npm:0.18.20" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/sunos-x64@npm:0.17.19" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/sunos-x64@npm:0.18.20" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-arm64@npm:0.17.19" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/win32-arm64@npm:0.18.20" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-ia32@npm:0.17.19" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/win32-ia32@npm:0.18.20" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-x64@npm:0.17.19" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/win32-x64@npm:0.18.20" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": + version: 4.4.0 + resolution: "@eslint-community/eslint-utils@npm:4.4.0" + dependencies: + eslint-visitor-keys: ^3.3.0 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: cdfe3ae42b4f572cbfb46d20edafe6f36fc5fb52bf2d90875c58aefe226892b9677fef60820e2832caf864a326fe4fc225714c46e8389ccca04d5f9288aabd22 + languageName: node + linkType: hard + +"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": + version: 4.10.0 + resolution: "@eslint-community/regexpp@npm:4.10.0" + checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b + languageName: node + linkType: hard + +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" + dependencies: + ajv: ^6.12.4 + debug: ^4.3.2 + espree: ^9.6.0 + globals: ^13.19.0 + ignore: ^5.2.0 + import-fresh: ^3.2.1 + js-yaml: ^4.1.0 + minimatch: ^3.1.2 + strip-json-comments: ^3.1.1 + checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 + languageName: node + linkType: hard + +"@eslint/js@npm:8.57.0": + version: 8.57.0 + resolution: "@eslint/js@npm:8.57.0" + checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb + languageName: node + linkType: hard + +"@esm-bundle/chai@npm:^4.3.4-fix.0": + version: 4.3.4 + resolution: "@esm-bundle/chai@npm:4.3.4" + dependencies: + "@types/chai": ^4.2.12 + checksum: 6d1237e9b8309b31ca55d12abe03642ab58550fdac24d0acbfeae6ab14182f72cedf646c6e858fd7ef592b4034ddd23ce5882ff22b8ab9b7952327e9f3f8c3f5 + languageName: node + linkType: hard + +"@ethersproject/abi@npm:^5.1.2": + version: 5.7.0 + resolution: "@ethersproject/abi@npm:5.7.0" + dependencies: + "@ethersproject/address": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/hash": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + checksum: bc6962bb6cb854e4d2a4d65b2c49c716477675b131b1363312234bdbb7e19badb7d9ce66f4ca2a70ae2ea84f7123dbc4e300a1bfe5d58864a7eafabc1466627e + languageName: node + linkType: hard + +"@ethersproject/abstract-provider@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/abstract-provider@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/networks": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/transactions": ^5.7.0 + "@ethersproject/web": ^5.7.0 + checksum: 74cf4696245cf03bb7cc5b6cbf7b4b89dd9a79a1c4688126d214153a938126d4972d42c93182198653ce1de35f2a2cad68be40337d4774b3698a39b28f0228a8 + languageName: node + linkType: hard + +"@ethersproject/abstract-signer@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/abstract-signer@npm:5.7.0" + dependencies: + "@ethersproject/abstract-provider": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + checksum: a823dac9cfb761e009851050ebebd5b229d1b1cc4a75b125c2da130ff37e8218208f7f9d1386f77407705b889b23d4a230ad67185f8872f083143e0073cbfbe3 + languageName: node + linkType: hard + +"@ethersproject/address@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/address@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/rlp": ^5.7.0 + checksum: 64ea5ebea9cc0e845c413e6cb1e54e157dd9fc0dffb98e239d3a3efc8177f2ff798cd4e3206cf3660ee8faeb7bef1a47dc0ebef0d7b132c32e61e550c7d4c843 + languageName: node + linkType: hard + +"@ethersproject/base64@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/base64@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + checksum: 7dd5d734d623582f08f665434f53685041a3d3b334a0e96c0c8afa8bbcaab934d50e5b6b980e826a8fde8d353e0b18f11e61faf17468177274b8e7c69cd9742b + languageName: node + linkType: hard + +"@ethersproject/bignumber@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/bignumber@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + bn.js: ^5.2.1 + checksum: 8c9a134b76f3feb4ec26a5a27379efb4e156b8fb2de0678a67788a91c7f4e30abe9d948638458e4b20f2e42380da0adacc7c9389d05fce070692edc6ae9b4904 + languageName: node + linkType: hard + +"@ethersproject/bytes@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/bytes@npm:5.7.0" + dependencies: + "@ethersproject/logger": ^5.7.0 + checksum: 66ad365ceaab5da1b23b72225c71dce472cf37737af5118181fa8ab7447d696bea15ca22e3a0e8836fdd8cfac161afe321a7c67d0dde96f9f645ddd759676621 + languageName: node + linkType: hard + +"@ethersproject/constants@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/constants@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": ^5.7.0 + checksum: 6d4b1355747cce837b3e76ec3bde70e4732736f23b04f196f706ebfa5d4d9c2be50904a390d4d40ce77803b98d03d16a9b6898418e04ba63491933ce08c4ba8a + languageName: node + linkType: hard + +"@ethersproject/hash@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/hash@npm:5.7.0" + dependencies: + "@ethersproject/abstract-signer": ^5.7.0 + "@ethersproject/address": ^5.7.0 + "@ethersproject/base64": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + checksum: 6e9fa8d14eb08171cd32f17f98cc108ec2aeca74a427655f0d689c550fee0b22a83b3b400fad7fb3f41cf14d4111f87f170aa7905bcbcd1173a55f21b06262ef + languageName: node + linkType: hard + +"@ethersproject/keccak256@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/keccak256@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + js-sha3: 0.8.0 + checksum: ff70950d82203aab29ccda2553422cbac2e7a0c15c986bd20a69b13606ed8bb6e4fdd7b67b8d3b27d4f841e8222cbaccd33ed34be29f866fec7308f96ed244c6 + languageName: node + linkType: hard + +"@ethersproject/logger@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/logger@npm:5.7.0" + checksum: 075ab2f605f1fd0813f2e39c3308f77b44a67732b36e712d9bc085f22a84aac4da4f71b39bee50fe78da3e1c812673fadc41180c9970fe5e486e91ea17befe0d + languageName: node + linkType: hard + +"@ethersproject/networks@npm:^5.7.0": + version: 5.7.1 + resolution: "@ethersproject/networks@npm:5.7.1" + dependencies: + "@ethersproject/logger": ^5.7.0 + checksum: 0339f312304c17d9a0adce550edb825d4d2c8c9468c1634c44172c67a9ed256f594da62c4cda5c3837a0f28b7fabc03aca9b492f68ff1fdad337ee861b27bd5d + languageName: node + linkType: hard + +"@ethersproject/properties@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/properties@npm:5.7.0" + dependencies: + "@ethersproject/logger": ^5.7.0 + checksum: 6ab0ccf0c3aadc9221e0cdc5306ce6cd0df7f89f77d77bccdd1277182c9ead0202cd7521329ba3acde130820bf8af299e17cf567d0d497c736ee918207bbf59f + languageName: node + linkType: hard + +"@ethersproject/rlp@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/rlp@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + checksum: bce165b0f7e68e4d091c9d3cf47b247cac33252df77a095ca4281d32d5eeaaa3695d9bc06b2b057c5015353a68df89f13a4a54a72e888e4beeabbe56b15dda6e + languageName: node + linkType: hard + +"@ethersproject/signing-key@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/signing-key@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + bn.js: ^5.2.1 + elliptic: 6.5.4 + hash.js: 1.1.7 + checksum: 8f8de09b0aac709683bbb49339bc0a4cd2f95598f3546436c65d6f3c3a847ffa98e06d35e9ed2b17d8030bd2f02db9b7bd2e11c5cf8a71aad4537487ab4cf03a + languageName: node + linkType: hard + +"@ethersproject/strings@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/strings@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + checksum: 5ff78693ae3fdf3cf23e1f6dc047a61e44c8197d2408c42719fef8cb7b7b3613a4eec88ac0ed1f9f5558c74fe0de7ae3195a29ca91a239c74b9f444d8e8b50df + languageName: node + linkType: hard + +"@ethersproject/transactions@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/transactions@npm:5.7.0" + dependencies: + "@ethersproject/address": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/rlp": ^5.7.0 + "@ethersproject/signing-key": ^5.7.0 + checksum: a31b71996d2b283f68486241bff0d3ea3f1ba0e8f1322a8fffc239ccc4f4a7eb2ea9994b8fd2f093283fd75f87bae68171e01b6265261f821369aca319884a79 + languageName: node + linkType: hard + +"@ethersproject/web@npm:^5.7.0": + version: 5.7.1 + resolution: "@ethersproject/web@npm:5.7.1" + dependencies: + "@ethersproject/base64": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + checksum: 7028c47103f82fd2e2c197ce0eecfacaa9180ffeec7de7845b1f4f9b19d84081b7a48227aaddde05a4aaa526af574a9a0ce01cc0fc75e3e371f84b38b5b16b2b + languageName: node + linkType: hard + +"@fastify/busboy@npm:^2.0.0": + version: 2.1.0 + resolution: "@fastify/busboy@npm:2.1.0" + checksum: 3233abd10f73e50668cb4bb278a79b7b3fadd30215ac6458299b0e5a09a29c3586ec07597aae6bd93f5cbedfcef43a8aeea51829cd28fc13850cdbcd324c28d5 + languageName: node + linkType: hard + +"@hapi/hoek@npm:^9.0.0": + version: 9.3.0 + resolution: "@hapi/hoek@npm:9.3.0" + checksum: 4771c7a776242c3c022b168046af4e324d116a9d2e1d60631ee64f474c6e38d1bb07092d898bf95c7bc5d334c5582798a1456321b2e53ca817d4e7c88bc25b43 + languageName: node + linkType: hard + +"@hapi/topo@npm:^5.0.0": + version: 5.1.0 + resolution: "@hapi/topo@npm:5.1.0" + dependencies: + "@hapi/hoek": ^9.0.0 + checksum: 604dfd5dde76d5c334bd03f9001fce69c7ce529883acf92da96f4fe7e51221bf5e5110e964caca287a6a616ba027c071748ab636ff178ad750547fba611d6014 + languageName: node + linkType: hard + +"@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.2 + debug: ^4.3.1 + minimatch: ^3.0.5 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 + languageName: node + linkType: hard + +"@humanwhocodes/module-importer@npm:^1.0.1": + version: 1.0.1 + resolution: "@humanwhocodes/module-importer@npm:1.0.1" + checksum: 0fd22007db8034a2cdf2c764b140d37d9020bbfce8a49d3ec5c05290e77d4b0263b1b972b752df8c89e5eaa94073408f2b7d977aed131faf6cf396ebb5d7fb61 + languageName: node + linkType: hard + +"@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 + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: ^5.1.2 + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: ^7.0.1 + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: ^8.1.0 + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb + languageName: node + linkType: hard + +"@jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" + dependencies: + "@sinclair/typebox": ^0.27.8 + checksum: 910040425f0fc93cd13e68c750b7885590b8839066dfa0cd78e7def07bbb708ad869381f725945d66f2284de5663bbecf63e8fdd856e2ae6e261ba30b1687e93 + languageName: node + linkType: hard + +"@jest/types@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/types@npm:29.6.3" + dependencies: + "@jest/schemas": ^29.6.3 + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^17.0.8 + chalk: ^4.0.0 + checksum: a0bcf15dbb0eca6bdd8ce61a3fb055349d40268622a7670a3b2eb3c3dbafe9eb26af59938366d520b86907b9505b0f9b29b85cec11579a9e580694b87cd90fcc + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": + version: 0.3.3 + resolution: "@jridgewell/gen-mapping@npm:0.3.3" + dependencies: + "@jridgewell/set-array": ^1.0.1 + "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.5 + resolution: "@jridgewell/gen-mapping@npm:0.3.5" + dependencies: + "@jridgewell/set-array": ^1.2.1 + "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/trace-mapping": ^0.3.24 + checksum: ff7a1764ebd76a5e129c8890aa3e2f46045109dabde62b0b6c6a250152227647178ff2069ea234753a690d8f3c4ac8b5e7b267bbee272bffb7f3b0a370ab6e52 + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.1 + resolution: "@jridgewell/resolve-uri@npm:3.1.1" + checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 + languageName: node + linkType: hard + +"@jridgewell/set-array@npm:^1.0.1": + version: 1.1.2 + resolution: "@jridgewell/set-array@npm:1.1.2" + checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e + languageName: node + linkType: hard + +"@jridgewell/set-array@npm:^1.2.1": + version: 1.2.1 + resolution: "@jridgewell/set-array@npm:1.2.1" + checksum: 832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 + languageName: node + linkType: hard + +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.5 + resolution: "@jridgewell/source-map@npm:0.3.5" + dependencies: + "@jridgewell/gen-mapping": ^0.3.0 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 1ad4dec0bdafbade57920a50acec6634f88a0eb735851e0dda906fa9894e7f0549c492678aad1a10f8e144bfe87f238307bf2a914a1bc85b7781d345417e9f6f + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" + dependencies: + "@jridgewell/resolve-uri": ^3.0.3 + "@jridgewell/sourcemap-codec": ^1.4.10 + checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.20 + resolution: "@jridgewell/trace-mapping@npm:0.3.20" + dependencies: + "@jridgewell/resolve-uri": ^3.1.0 + "@jridgewell/sourcemap-codec": ^1.4.14 + checksum: cd1a7353135f385909468ff0cf20bdd37e59f2ee49a13a966dedf921943e222082c583ade2b579ff6cd0d8faafcb5461f253e1bf2a9f48fec439211fdbe788f5 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" + dependencies: + "@jridgewell/resolve-uri": ^3.1.0 + "@jridgewell/sourcemap-codec": ^1.4.14 + checksum: 9d3c40d225e139987b50c48988f8717a54a8c994d8a948ee42e1412e08988761d0754d7d10b803061cc3aebf35f92a5dbbab493bd0e1a9ef9e89a2130e83ba34 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.20": + version: 0.3.22 + resolution: "@jridgewell/trace-mapping@npm:0.3.22" + dependencies: + "@jridgewell/resolve-uri": ^3.1.0 + "@jridgewell/sourcemap-codec": ^1.4.14 + checksum: ac7dd2cfe0b479aa1b81776d40d789243131cc792dc8b6b6a028c70fcd6171958ae1a71bf67b618ffe3c0c3feead9870c095ee46a5e30319410d92976b28f498 + languageName: node + linkType: hard + +"@leichtgewicht/ip-codec@npm:^2.0.1": + version: 2.0.4 + resolution: "@leichtgewicht/ip-codec@npm:2.0.4" + checksum: 468de1f04d33de6d300892683d7c8aecbf96d1e2c5fe084f95f816e50a054d45b7c1ebfb141a1447d844b86a948733f6eebd92234da8581c84a1ad4de2946a2d + languageName: node + linkType: hard + +"@ltd/j-toml@npm:^1.38.0": + version: 1.38.0 + resolution: "@ltd/j-toml@npm:1.38.0" + checksum: 34f5d0ec652e790a7a733f0d3a8d9957d63997bd0efc13a61beb9d772bae75519453884fbc3fd6a2d5fe15674834bdd57ca1824bb1de8f829e5ce195fc5fa3ea + languageName: node + linkType: hard + +"@mdn/browser-compat-data@npm:^4.0.0": + version: 4.2.1 + resolution: "@mdn/browser-compat-data@npm:4.2.1" + checksum: 76eaa7dafed154040e769ba6d23f2dcb58e805ed3ccb376a5c4b76326c92643753c20194faed363870800dc3c1af26c107b8562710c8bb37aaee8c5ffe2a89cd + languageName: node + linkType: hard + +"@mdx-js/mdx@npm:^1.6.22": + version: 1.6.22 + resolution: "@mdx-js/mdx@npm:1.6.22" + dependencies: + "@babel/core": 7.12.9 + "@babel/plugin-syntax-jsx": 7.12.1 + "@babel/plugin-syntax-object-rest-spread": 7.8.3 + "@mdx-js/util": 1.6.22 + babel-plugin-apply-mdx-type-prop: 1.6.22 + babel-plugin-extract-import-names: 1.6.22 + camelcase-css: 2.0.1 + detab: 2.0.4 + hast-util-raw: 6.0.1 + lodash.uniq: 4.5.0 + mdast-util-to-hast: 10.0.1 + remark-footnotes: 2.0.0 + remark-mdx: 1.6.22 + remark-parse: 8.0.3 + remark-squeeze-paragraphs: 4.0.0 + style-to-object: 0.3.0 + unified: 9.2.0 + unist-builder: 2.0.3 + unist-util-visit: 2.0.3 + checksum: 0839b4a3899416326ea6578fe9e470af319da559bc6d3669c60942e456b49a98eebeb3358c623007b4786a2175a450d2c51cd59df64639013c5a3d22366931a6 + languageName: node + linkType: hard + +"@mdx-js/mdx@npm:^3.0.0": + version: 3.0.0 + resolution: "@mdx-js/mdx@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdx": ^2.0.0 + collapse-white-space: ^2.0.0 + devlop: ^1.0.0 + estree-util-build-jsx: ^3.0.0 + estree-util-is-identifier-name: ^3.0.0 + estree-util-to-js: ^2.0.0 + estree-walker: ^3.0.0 + hast-util-to-estree: ^3.0.0 + hast-util-to-jsx-runtime: ^2.0.0 + markdown-extensions: ^2.0.0 + periscopic: ^3.0.0 + remark-mdx: ^3.0.0 + remark-parse: ^11.0.0 + remark-rehype: ^11.0.0 + source-map: ^0.7.0 + unified: ^11.0.0 + unist-util-position-from-estree: ^2.0.0 + unist-util-stringify-position: ^4.0.0 + unist-util-visit: ^5.0.0 + vfile: ^6.0.0 + checksum: da4305dcfd9012521170e0ed439eb336900fb84a5784e5e3dac2144855fa603325477855e17a04b7c673cc24699cf2bfd611c958f591bb3a9afb5608c259bbd3 + languageName: node + linkType: hard + +"@mdx-js/react@npm:^3.0.0": + version: 3.0.0 + resolution: "@mdx-js/react@npm:3.0.0" + dependencies: + "@types/mdx": ^2.0.0 + peerDependencies: + "@types/react": ">=16" + react: ">=16" + checksum: a780cff9d7f7639d6fc21c9d4e0a6ac1370c3209ea0db176923df7f9145785309591cf871f227f5135d1fe2accce0d5df9a22fc0530e5dda0c7b4b105705f20d + languageName: node + linkType: hard + +"@mdx-js/util@npm:1.6.22": + version: 1.6.22 + resolution: "@mdx-js/util@npm:1.6.22" + checksum: 4b393907e39a1a75214f0314bf72a0adfa5e5adffd050dd5efe9c055b8549481a3cfc9f308c16dfb33311daf3ff63added7d5fd1fe52db614c004f886e0e559a + languageName: node + linkType: hard + +"@metamask/eth-sig-util@npm:^4.0.0": + version: 4.0.1 + resolution: "@metamask/eth-sig-util@npm:4.0.1" + dependencies: + ethereumjs-abi: ^0.6.8 + ethereumjs-util: ^6.2.1 + ethjs-util: ^0.1.6 + tweetnacl: ^1.0.3 + tweetnacl-util: ^0.15.1 + checksum: 740df4c92a1282e6be4c00c86c1a8ccfb93e767596e43f6da895aa5bab4a28fc3c2209f0327db34924a4a1e9db72bc4d3dddfcfc45cca0b218c9ccbf7d1b1445 + languageName: node + linkType: hard + +"@noble/curves@npm:1.2.0": + version: 1.2.0 + resolution: "@noble/curves@npm:1.2.0" + dependencies: + "@noble/hashes": 1.3.2 + checksum: bb798d7a66d8e43789e93bc3c2ddff91a1e19fdb79a99b86cd98f1e5eff0ee2024a2672902c2576ef3577b6f282f3b5c778bebd55761ddbb30e36bf275e83dd0 + languageName: node + linkType: hard + +"@noble/hashes@npm:1.2.0, @noble/hashes@npm:~1.2.0": + version: 1.2.0 + resolution: "@noble/hashes@npm:1.2.0" + checksum: 8ca080ce557b8f40fb2f78d3aedffd95825a415ac8e13d7ffe3643f8626a8c2d99a3e5975b555027ac24316d8b3c02a35b8358567c0c23af681e6573602aa434 + languageName: node + linkType: hard + +"@noble/hashes@npm:1.3.2": + version: 1.3.2 + resolution: "@noble/hashes@npm:1.3.2" + checksum: fe23536b436539d13f90e4b9be843cc63b1b17666a07634a2b1259dded6f490be3d050249e6af98076ea8f2ea0d56f578773c2197f2aa0eeaa5fba5bc18ba474 + languageName: node + linkType: hard + +"@noble/secp256k1@npm:1.7.1, @noble/secp256k1@npm:~1.7.0": + version: 1.7.1 + resolution: "@noble/secp256k1@npm:1.7.1" + checksum: d2301f1f7690368d8409a3152450458f27e54df47e3f917292de3de82c298770890c2de7c967d237eff9c95b70af485389a9695f73eb05a43e2bd562d18b18cb + languageName: node + linkType: hard + +"@node-rs/jieba-android-arm-eabi@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-android-arm-eabi@npm:1.7.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@node-rs/jieba-android-arm64@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-android-arm64@npm:1.7.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@node-rs/jieba-darwin-arm64@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-darwin-arm64@npm:1.7.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@node-rs/jieba-darwin-x64@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-darwin-x64@npm:1.7.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@node-rs/jieba-freebsd-x64@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-freebsd-x64@npm:1.7.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@node-rs/jieba-linux-arm-gnueabihf@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-linux-arm-gnueabihf@npm:1.7.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@node-rs/jieba-linux-arm64-gnu@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-linux-arm64-gnu@npm:1.7.2" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@node-rs/jieba-linux-arm64-musl@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-linux-arm64-musl@npm:1.7.2" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@node-rs/jieba-linux-x64-gnu@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-linux-x64-gnu@npm:1.7.2" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@node-rs/jieba-linux-x64-musl@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-linux-x64-musl@npm:1.7.2" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@node-rs/jieba-win32-arm64-msvc@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-win32-arm64-msvc@npm:1.7.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@node-rs/jieba-win32-ia32-msvc@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-win32-ia32-msvc@npm:1.7.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@node-rs/jieba-win32-x64-msvc@npm:1.7.2": + version: 1.7.2 + resolution: "@node-rs/jieba-win32-x64-msvc@npm:1.7.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@node-rs/jieba@npm:^1.6.0": + version: 1.7.2 + resolution: "@node-rs/jieba@npm:1.7.2" + dependencies: + "@node-rs/jieba-android-arm-eabi": 1.7.2 + "@node-rs/jieba-android-arm64": 1.7.2 + "@node-rs/jieba-darwin-arm64": 1.7.2 + "@node-rs/jieba-darwin-x64": 1.7.2 + "@node-rs/jieba-freebsd-x64": 1.7.2 + "@node-rs/jieba-linux-arm-gnueabihf": 1.7.2 + "@node-rs/jieba-linux-arm64-gnu": 1.7.2 + "@node-rs/jieba-linux-arm64-musl": 1.7.2 + "@node-rs/jieba-linux-x64-gnu": 1.7.2 + "@node-rs/jieba-linux-x64-musl": 1.7.2 + "@node-rs/jieba-win32-arm64-msvc": 1.7.2 + "@node-rs/jieba-win32-ia32-msvc": 1.7.2 + "@node-rs/jieba-win32-x64-msvc": 1.7.2 + dependenciesMeta: + "@node-rs/jieba-android-arm-eabi": + optional: true + "@node-rs/jieba-android-arm64": + optional: true + "@node-rs/jieba-darwin-arm64": + optional: true + "@node-rs/jieba-darwin-x64": + optional: true + "@node-rs/jieba-freebsd-x64": + optional: true + "@node-rs/jieba-linux-arm-gnueabihf": + optional: true + "@node-rs/jieba-linux-arm64-gnu": + optional: true + "@node-rs/jieba-linux-arm64-musl": + optional: true + "@node-rs/jieba-linux-x64-gnu": + optional: true + "@node-rs/jieba-linux-x64-musl": + optional: true + "@node-rs/jieba-win32-arm64-msvc": + optional: true + "@node-rs/jieba-win32-ia32-msvc": + optional: true + "@node-rs/jieba-win32-x64-msvc": + optional: true + checksum: 47108c5e84993ba2ddbc1d922ecb840b74668d61ff8ec83137a300c02e6c97748e64d98f23484dce7d1aee9d00dcf3d1921ccb5375b83ed8474650d0fc1e7e60 + languageName: node + linkType: hard + +"@nodelib/fs.scandir@npm:2.1.5": + version: 2.1.5 + resolution: "@nodelib/fs.scandir@npm:2.1.5" + dependencies: + "@nodelib/fs.stat": 2.0.5 + run-parallel: ^1.1.9 + checksum: a970d595bd23c66c880e0ef1817791432dbb7acbb8d44b7e7d0e7a22f4521260d4a83f7f9fd61d44fda4610105577f8f58a60718105fb38352baed612fd79e59 + languageName: node + linkType: hard + +"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": + version: 2.0.5 + resolution: "@nodelib/fs.stat@npm:2.0.5" + checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 + languageName: node + linkType: hard + +"@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": + version: 1.2.8 + resolution: "@nodelib/fs.walk@npm:1.2.8" + dependencies: + "@nodelib/fs.scandir": 2.1.5 + fastq: ^1.6.0 + checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53 + languageName: node + linkType: hard + +"@noir-lang/acvm_js@workspace:*, @noir-lang/acvm_js@workspace:acvm-repo/acvm_js": + version: 0.0.0-use.local + resolution: "@noir-lang/acvm_js@workspace:acvm-repo/acvm_js" + dependencies: + "@esm-bundle/chai": ^4.3.4-fix.0 + "@web/dev-server-esbuild": ^0.3.6 + "@web/test-runner": ^0.18.1 + "@web/test-runner-playwright": ^0.11.0 + chai: ^4.4.1 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 + mocha: ^10.2.0 + prettier: 3.2.5 + ts-node: ^10.9.1 + typescript: ^5.4.2 + languageName: unknown + linkType: soft + +"@noir-lang/noir_codegen@workspace:tooling/noir_codegen": + version: 0.0.0-use.local + resolution: "@noir-lang/noir_codegen@workspace:tooling/noir_codegen" + dependencies: + "@noir-lang/noir_js": "workspace:*" + "@noir-lang/types": "workspace:*" + "@types/chai": ^4 + "@types/mocha": ^10.0.1 + "@types/node": ^20.6.2 + "@types/prettier": ^3 + chai: ^4.4.1 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 + glob: ^10.3.10 + mocha: ^10.2.0 + prettier: 3.2.5 + ts-command-line-args: ^2.5.1 + ts-node: ^10.9.1 + tsx: ^4.6.2 + typescript: ^5.4.2 + bin: + noir-codegen: lib/main.js + languageName: unknown + linkType: soft + +"@noir-lang/noir_js@workspace:*, @noir-lang/noir_js@workspace:tooling/noir_js": + version: 0.0.0-use.local + resolution: "@noir-lang/noir_js@workspace:tooling/noir_js" + dependencies: + "@noir-lang/acvm_js": "workspace:*" + "@noir-lang/noirc_abi": "workspace:*" + "@noir-lang/types": "workspace:*" + "@types/chai": ^4 + "@types/mocha": ^10.0.1 + "@types/node": ^20.6.2 + "@types/prettier": ^3 + chai: ^4.4.1 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 + mocha: ^10.2.0 + prettier: 3.2.5 + ts-node: ^10.9.1 + tsc-multi: ^1.1.0 + tsx: ^4.6.2 + typescript: ^5.4.2 + languageName: unknown + linkType: soft + +"@noir-lang/noir_wasm@workspace:*, @noir-lang/noir_wasm@workspace:compiler/wasm": + version: 0.0.0-use.local + resolution: "@noir-lang/noir_wasm@workspace:compiler/wasm" + dependencies: + "@esm-bundle/chai": ^4.3.4-fix.0 + "@ltd/j-toml": ^1.38.0 + "@noir-lang/types": "workspace:*" + "@types/adm-zip": ^0.5.0 + "@types/chai": ^4 + "@types/mocha": ^10.0.6 + "@types/mocha-each": ^2 + "@types/node": ^20.10.5 + "@types/pako": ^2 + "@types/path-browserify": ^1 + "@types/readable-stream": ^4 + "@types/sinon": ^17 + "@wasm-tool/wasm-pack-plugin": ^1.7.0 + "@web/dev-server-esbuild": ^0.3.6 + "@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.4.1 + copy-webpack-plugin: ^12.0.2 + 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.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.4.2 + unzipit: ^1.4.3 + url: ^0.11.3 + webpack: ^5.90.1 + webpack-cli: ^5.1.4 + webpack-dev-server: ^5.0.0 + languageName: unknown + linkType: soft + +"@noir-lang/noirc_abi@workspace:*, @noir-lang/noirc_abi@workspace:tooling/noirc_abi_wasm": + version: 0.0.0-use.local + resolution: "@noir-lang/noirc_abi@workspace:tooling/noirc_abi_wasm" + dependencies: + "@esm-bundle/chai": ^4.3.4-fix.0 + "@noir-lang/types": "workspace:*" + "@web/dev-server-esbuild": ^0.3.6 + "@web/test-runner": ^0.18.1 + "@web/test-runner-playwright": ^0.11.0 + eslint: ^8.57.0 + mocha: ^10.2.0 + languageName: unknown + linkType: soft + +"@noir-lang/root@workspace:.": + version: 0.0.0-use.local + resolution: "@noir-lang/root@workspace:." + dependencies: + "@typescript-eslint/eslint-plugin": ^6.7.3 + "@typescript-eslint/parser": ^6.7.3 + chai: ^4.4.1 + cspell: ^8.3.2 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 + mocha: ^10.2.0 + prettier: 3.2.5 + ts-node: ^10.9.1 + typescript: ^5.4.2 + languageName: unknown + linkType: soft + +"@noir-lang/types@workspace:*, @noir-lang/types@workspace:tooling/noir_js_types": + version: 0.0.0-use.local + resolution: "@noir-lang/types@workspace:tooling/noir_js_types" + dependencies: + "@types/prettier": ^3 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 + prettier: 3.2.5 + typescript: ^5.4.2 + languageName: unknown + linkType: soft + +"@nomicfoundation/edr-darwin-arm64@npm:0.4.2": + version: 0.4.2 + resolution: "@nomicfoundation/edr-darwin-arm64@npm:0.4.2" + checksum: 7835e998c2ef83924efac0694bb4392f6abf770dc7f935dd28abc1a291f830cade14750d83a46a3205338e4ddff943dda60a9849317cf42edd38d7a2ce843588 + languageName: node + linkType: hard + +"@nomicfoundation/edr-darwin-x64@npm:0.4.2": + version: 0.4.2 + resolution: "@nomicfoundation/edr-darwin-x64@npm:0.4.2" + checksum: 94daa26610621e85cb025feb37bb93e9b89c59f908bf3eae70720d2b86632dbb1236420ae3ae6f685d563ba52519d5f860e68ccd898fa1fced831961dea2c08a + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-arm64-gnu@npm:0.4.2": + version: 0.4.2 + resolution: "@nomicfoundation/edr-linux-arm64-gnu@npm:0.4.2" + checksum: a7181e237f6ece8bd97e0f75972044dbf584c506bbac5bef586d9f7d627a2c07a279a2d892837bbedc80ea3dfb39fa66becc297238b5d715a942eed2a50745cd + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-arm64-musl@npm:0.4.2": + version: 0.4.2 + resolution: "@nomicfoundation/edr-linux-arm64-musl@npm:0.4.2" + checksum: 5a849484b7a104a7e1497774c4117afc58f64d57d30889d4f6f676dddb5c695192c0789b8be0b71171a2af770167a28aa301ae3ece7a2a156d82d94388639b66 + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-x64-gnu@npm:0.4.2": + version: 0.4.2 + resolution: "@nomicfoundation/edr-linux-x64-gnu@npm:0.4.2" + checksum: 0520dd9a583976fd0f49dfe6c23227f03cd811a395dc5eed1a2922b4358d7c71fdcfea8f389d4a0e23b4ec53e1435959a544380f94e48122a75f94a42b177ac7 + languageName: node + linkType: hard + +"@nomicfoundation/edr-linux-x64-musl@npm:0.4.2": + version: 0.4.2 + resolution: "@nomicfoundation/edr-linux-x64-musl@npm:0.4.2" + checksum: 80c3b4346d8c27539bc005b09db233dedd8930310d1a049827661e69a8e03be9cbac27eb620a6ae9bfd46a2fbe22f83cee5af8d9e63178925d74d9c656246708 + languageName: node + linkType: hard + +"@nomicfoundation/edr-win32-x64-msvc@npm:0.4.2": + version: 0.4.2 + resolution: "@nomicfoundation/edr-win32-x64-msvc@npm:0.4.2" + checksum: 736fb866fd5c2708560cbd5ae72815b5fc96e650cd74bc8bab0a1cb0e8baede4f595fdceb445c159814a6a7e8e691de227a5db49f61b3cd0ddfafd5715b397ab + languageName: node + linkType: hard + +"@nomicfoundation/edr@npm:^0.4.1": + version: 0.4.2 + resolution: "@nomicfoundation/edr@npm:0.4.2" + dependencies: + "@nomicfoundation/edr-darwin-arm64": 0.4.2 + "@nomicfoundation/edr-darwin-x64": 0.4.2 + "@nomicfoundation/edr-linux-arm64-gnu": 0.4.2 + "@nomicfoundation/edr-linux-arm64-musl": 0.4.2 + "@nomicfoundation/edr-linux-x64-gnu": 0.4.2 + "@nomicfoundation/edr-linux-x64-musl": 0.4.2 + "@nomicfoundation/edr-win32-x64-msvc": 0.4.2 + checksum: 8c8457257b59ed9a29d88b7492e98e974d24e8318903e876a14dc0f6d5dc77948cd9053937d9730f54f920ba82ce3d244cab518d068359bcc20df88623f171ef + languageName: node + linkType: hard + +"@nomicfoundation/ethereumjs-common@npm:4.0.4": + version: 4.0.4 + resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.4" + dependencies: + "@nomicfoundation/ethereumjs-util": 9.0.4 + checksum: ce3f6e4ae15b976efdb7ccda27e19aadb62b5ffee209f9503e68b4fd8633715d4d697c0cc10ccd35f5e4e977edd05100d0f214e28880ec64fff77341dc34fcdf + languageName: node + linkType: hard + +"@nomicfoundation/ethereumjs-rlp@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.4" + bin: + rlp: bin/rlp.cjs + checksum: ee2c2e5776c73801dc5ed636f4988b599b4563c2d0037da542ea57eb237c69dd1ac555f6bcb5e06f70515b6459779ba0d68252a6e105132b4659ab4bf62919b0 + languageName: node + linkType: hard + +"@nomicfoundation/ethereumjs-tx@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.4" + dependencies: + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + ethereum-cryptography: 0.1.3 + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + checksum: 0f1c87716682ccbcf4d92ffc6cf8ab557e658b90319d82be3219a091a736859f8803c73c98e4863682e3e86d264751c472d33ff6d3c3daf4e75b5f01d0af8fa3 + languageName: node + linkType: hard + +"@nomicfoundation/ethereumjs-util@npm:9.0.4": + version: 9.0.4 + resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.4" + dependencies: + "@nomicfoundation/ethereumjs-rlp": 5.0.4 + ethereum-cryptography: 0.1.3 + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + checksum: 754439f72b11cad2d8986707ad020077dcc763c4055f73e2668a0b4cadb22aa4407faa9b3c587d9eb5b97ac337afbe037eb642bc1d5a16197284f83db3462cbe + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-chai-matchers@npm:^2.0.0": + version: 2.0.2 + resolution: "@nomicfoundation/hardhat-chai-matchers@npm:2.0.2" + dependencies: + "@types/chai-as-promised": ^7.1.3 + chai-as-promised: ^7.1.1 + deep-eql: ^4.0.1 + ordinal: ^1.0.3 + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.0 + chai: ^4.2.0 + ethers: ^6.1.0 + hardhat: ^2.9.4 + checksum: 62d7d69f6b34a06bc43fe0dab8adc9e3b6f907f1b68bb5cf47feb78a4c7ef057b9a4aa713611abeca38df9d8fe166bbd9bbf98e42c4edbdf7aece477b3f9485a + languageName: node + linkType: hard + +"@nomicfoundation/hardhat-ethers@npm:^3.0.0": + version: 3.0.5 + resolution: "@nomicfoundation/hardhat-ethers@npm:3.0.5" + dependencies: + debug: ^4.1.1 + lodash.isequal: ^4.5.0 + peerDependencies: + ethers: ^6.1.0 + hardhat: ^2.0.0 + checksum: 34b092dfec68f8d8673c96af717660327edc814bc5c9cdb5bc1f82d5bde2b18bc9b9d3499a632784a3d4f2505ac174217e55d31b546b7eaa77a5bb30b3c80bb4 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-darwin-x64@npm:0.1.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-freebsd-x64@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-freebsd-x64@npm:0.1.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-gnu@npm:0.1.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-linux-arm64-musl@npm:0.1.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-linux-x64-gnu@npm:0.1.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-linux-x64-musl@npm:0.1.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-win32-arm64-msvc@npm:0.1.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-win32-ia32-msvc@npm:0.1.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.1": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer-win32-x64-msvc@npm:0.1.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@nomicfoundation/solidity-analyzer@npm:^0.1.0": + version: 0.1.1 + resolution: "@nomicfoundation/solidity-analyzer@npm:0.1.1" + dependencies: + "@nomicfoundation/solidity-analyzer-darwin-arm64": 0.1.1 + "@nomicfoundation/solidity-analyzer-darwin-x64": 0.1.1 + "@nomicfoundation/solidity-analyzer-freebsd-x64": 0.1.1 + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": 0.1.1 + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": 0.1.1 + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": 0.1.1 + "@nomicfoundation/solidity-analyzer-linux-x64-musl": 0.1.1 + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": 0.1.1 + "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": 0.1.1 + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": 0.1.1 + dependenciesMeta: + "@nomicfoundation/solidity-analyzer-darwin-arm64": + optional: true + "@nomicfoundation/solidity-analyzer-darwin-x64": + optional: true + "@nomicfoundation/solidity-analyzer-freebsd-x64": + optional: true + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": + optional: true + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": + optional: true + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": + optional: true + "@nomicfoundation/solidity-analyzer-linux-x64-musl": + optional: true + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": + optional: true + "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": + optional: true + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": + optional: true + checksum: 038cffafd5769e25256b5b8bef88d95cc1c021274a65c020cf84aceb3237752a3b51645fdb0687f5516a2bdfebf166fcf50b08ab64857925100213e0654b266b + languageName: node + linkType: hard + +"@npmcli/agent@npm:^2.0.0": + version: 2.2.0 + resolution: "@npmcli/agent@npm:2.2.0" + dependencies: + agent-base: ^7.1.0 + http-proxy-agent: ^7.0.0 + https-proxy-agent: ^7.0.1 + lru-cache: ^10.0.1 + socks-proxy-agent: ^8.0.1 + checksum: 3b25312edbdfaa4089af28e2d423b6f19838b945e47765b0c8174c1395c79d43c3ad6d23cb364b43f59fd3acb02c93e3b493f72ddbe3dfea04c86843a7311fc4 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.0 + resolution: "@npmcli/fs@npm:3.1.0" + dependencies: + semver: ^7.3.5 + checksum: a50a6818de5fc557d0b0e6f50ec780a7a02ab8ad07e5ac8b16bf519e0ad60a144ac64f97d05c443c3367235d337182e1d012bbac0eb8dbae8dc7b40b193efd0e + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f + languageName: node + linkType: hard + +"@pkgr/core@npm:^0.1.0": + version: 0.1.1 + resolution: "@pkgr/core@npm:0.1.1" + checksum: 6f25fd2e3008f259c77207ac9915b02f1628420403b2630c92a07ff963129238c9262afc9e84344c7a23b5cc1f3965e2cd17e3798219f5fd78a63d144d3cceba + languageName: node + linkType: hard + +"@pnpm/config.env-replace@npm:^1.1.0": + version: 1.1.0 + resolution: "@pnpm/config.env-replace@npm:1.1.0" + checksum: a3d2b57e35eec9543d9eb085854f6e33e8102dac99fdef2fad2eebdbbfc345e93299f0c20e8eb61c1b4c7aa123bfd47c175678626f161cda65dd147c2b6e1fa0 + languageName: node + linkType: hard + +"@pnpm/network.ca-file@npm:^1.0.1": + version: 1.0.2 + resolution: "@pnpm/network.ca-file@npm:1.0.2" + dependencies: + graceful-fs: 4.2.10 + checksum: d8d0884646500576bd5390464d13db1bb9a62e32a1069293e5bddb2ad8354b354b7e2d2a35e12850025651e795e6a80ce9e601c66312504667b7e3ee7b52becc + languageName: node + linkType: hard + +"@pnpm/npm-conf@npm:^2.1.0": + version: 2.2.2 + resolution: "@pnpm/npm-conf@npm:2.2.2" + dependencies: + "@pnpm/config.env-replace": ^1.1.0 + "@pnpm/network.ca-file": ^1.0.1 + config-chain: ^1.1.11 + checksum: d64aa4464be584caa855eafa8f109509390489997e36d602d6215784e2973b896bef3968426bb00896cf4ae7d440fed2cee7bb4e0dbc90362f024ea3f9e27ab1 + languageName: node + linkType: hard + +"@polka/url@npm:^1.0.0-next.20": + version: 1.0.0-next.24 + resolution: "@polka/url@npm:1.0.0-next.24" + checksum: 00baec4458ac86ca27edf7ce807ccfad97cd1d4b67bdedaf3401a9e755757588f3331e891290d1deea52d88df2bf2387caf8d94a6835b614d5b37b638a688273 + languageName: node + linkType: hard + +"@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.4.0 + semver: 7.6.0 + tar-fs: 3.0.5 + unbzip2-stream: 1.4.3 + yargs: 17.7.2 + bin: + browsers: lib/cjs/main-cli.js + checksum: 318740056fc716cf26179f053eb47e119bc01658f59382a19fb7d39e5b9232a7ad7d82e33445e0519683c13e22b328193fc9952c99d09cdc09f6539391d4749c + languageName: node + linkType: hard + +"@rollup/plugin-node-resolve@npm:^15.0.1": + version: 15.2.3 + resolution: "@rollup/plugin-node-resolve@npm:15.2.3" + dependencies: + "@rollup/pluginutils": ^5.0.1 + "@types/resolve": 1.20.2 + deepmerge: ^4.2.2 + is-builtin-module: ^3.2.1 + is-module: ^1.0.0 + resolve: ^1.22.1 + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 730f32c2f8fdddff07cf0fca86a5dac7c475605fb96930197a868c066e62eb6388c557545e4f7d99b7a283411754c9fbf98944ab086b6074e04fc1292e234aa8 + languageName: node + linkType: hard + +"@rollup/pluginutils@npm:^5.0.1": + version: 5.1.0 + resolution: "@rollup/pluginutils@npm:5.1.0" + dependencies: + "@types/estree": ^1.0.0 + estree-walker: ^2.0.2 + picomatch: ^2.3.1 + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 3cc5a6d91452a6eabbfd1ae79b4dd1f1e809d2eecda6e175deb784e75b0911f47e9ecce73f8dd315d6a8b3f362582c91d3c0f66908b6ced69345b3cbe28f8ce8 + languageName: node + linkType: hard + +"@rollup/rollup-android-arm-eabi@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.9.4" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-android-arm64@npm:4.9.4" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-darwin-arm64@npm:4.9.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-darwin-x64@npm:4.9.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.9.4" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.9.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.9.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.9.4" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.9.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.9.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.9.4" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.9.4" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.9.4": + version: 4.9.4 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.9.4" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@scure/base@npm:~1.1.0": + version: 1.1.3 + resolution: "@scure/base@npm:1.1.3" + checksum: 1606ab8a4db898cb3a1ada16c15437c3bce4e25854fadc8eb03ae93cbbbac1ed90655af4b0be3da37e12056fef11c0374499f69b9e658c9e5b7b3e06353c630c + languageName: node + linkType: hard + +"@scure/bip32@npm:1.1.5": + version: 1.1.5 + resolution: "@scure/bip32@npm:1.1.5" + dependencies: + "@noble/hashes": ~1.2.0 + "@noble/secp256k1": ~1.7.0 + "@scure/base": ~1.1.0 + checksum: b08494ab0d2b1efee7226d1b5100db5157ebea22a78bb87126982a76a186cb3048413e8be0ba2622d00d048a20acbba527af730de86c132a77de616eb9907a3b + languageName: node + linkType: hard + +"@scure/bip39@npm:1.1.1": + version: 1.1.1 + resolution: "@scure/bip39@npm:1.1.1" + dependencies: + "@noble/hashes": ~1.2.0 + "@scure/base": ~1.1.0 + checksum: fbb594c50696fa9c14e891d872f382e50a3f919b6c96c55ef2fb10c7102c546dafb8f099a62bd114c12a00525b595dcf7381846f383f0ddcedeaa6e210747d2f + languageName: node + linkType: hard + +"@sentry/core@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/core@npm:5.30.0" + dependencies: + "@sentry/hub": 5.30.0 + "@sentry/minimal": 5.30.0 + "@sentry/types": 5.30.0 + "@sentry/utils": 5.30.0 + tslib: ^1.9.3 + checksum: 8a2b22687e70d76fa4381bce215d770b6c08561c5ff5d6afe39c8c3c509c18ee7384ad0be3aee18d3a858a3c88e1d2821cf10eb5e05646376a33200903b56da2 + languageName: node + linkType: hard + +"@sentry/hub@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/hub@npm:5.30.0" + dependencies: + "@sentry/types": 5.30.0 + "@sentry/utils": 5.30.0 + tslib: ^1.9.3 + checksum: 09f778cc78765213f1e35a3ee6da3a8e02a706e8a7e5b7f84614707f4b665c7297b700a1849ab2ca1f02ede5884fd9ae893e58dc65f04f35ccdfee17e99ee93d + languageName: node + linkType: hard + +"@sentry/minimal@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/minimal@npm:5.30.0" + dependencies: + "@sentry/hub": 5.30.0 + "@sentry/types": 5.30.0 + tslib: ^1.9.3 + checksum: 934650f6989ce51f425c7c4b4d4d9bfecface8162a36d21df8a241f780ab1716dd47b81e2170e4cc624797ed1eebe10f71e4876c1e25b787860daaef75ca7a0c + languageName: node + linkType: hard + +"@sentry/node@npm:^5.18.1": + version: 5.30.0 + resolution: "@sentry/node@npm:5.30.0" + dependencies: + "@sentry/core": 5.30.0 + "@sentry/hub": 5.30.0 + "@sentry/tracing": 5.30.0 + "@sentry/types": 5.30.0 + "@sentry/utils": 5.30.0 + cookie: ^0.4.1 + https-proxy-agent: ^5.0.0 + lru_map: ^0.3.3 + tslib: ^1.9.3 + checksum: 5f0367cc52f9d716c64ba727e2a5c8592364494c8fdadfb3df2d0ee9d7956b886fb3ec674370292d2a7b7e1d9a8e1b84c69c06e8a4a064be8d4687698df0090c + languageName: node + linkType: hard + +"@sentry/tracing@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/tracing@npm:5.30.0" + dependencies: + "@sentry/hub": 5.30.0 + "@sentry/minimal": 5.30.0 + "@sentry/types": 5.30.0 + "@sentry/utils": 5.30.0 + tslib: ^1.9.3 + checksum: 720c07b111e8128e70a939ab4e9f9cfd13dc23303b27575afddabab08d08f9b94499017c76a9ffe253bf3ca40833e8f9262cf6dc546ba24da6eb74fedae5f92b + languageName: node + linkType: hard + +"@sentry/types@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/types@npm:5.30.0" + checksum: de7df777824c8e311f143c6fd7de220b24f25b5018312fe8f67d93bebf0f3cdd32bbca9f155846f5c31441d940eebe27c8338000321559a743264c7e41dda560 + languageName: node + linkType: hard + +"@sentry/utils@npm:5.30.0": + version: 5.30.0 + resolution: "@sentry/utils@npm:5.30.0" + dependencies: + "@sentry/types": 5.30.0 + tslib: ^1.9.3 + checksum: 27b259a136c664427641dd32ee3dc490553f3b5e92986accfa829d14063ebc69b191e92209ac9c40fbc367f74cfa17dc93b4c40981d666711fd57b4d51a82062 + languageName: node + linkType: hard + +"@sideway/address@npm:^4.1.3": + version: 4.1.4 + resolution: "@sideway/address@npm:4.1.4" + dependencies: + "@hapi/hoek": ^9.0.0 + checksum: b9fca2a93ac2c975ba12e0a6d97853832fb1f4fb02393015e012b47fa916a75ca95102d77214b2a29a2784740df2407951af8c5dde054824c65577fd293c4cdb + languageName: node + linkType: hard + +"@sideway/formula@npm:^3.0.1": + version: 3.0.1 + resolution: "@sideway/formula@npm:3.0.1" + checksum: e4beeebc9dbe2ff4ef0def15cec0165e00d1612e3d7cea0bc9ce5175c3263fc2c818b679bd558957f49400ee7be9d4e5ac90487e1625b4932e15c4aa7919c57a + languageName: node + linkType: hard + +"@sideway/pinpoint@npm:^2.0.0": + version: 2.0.0 + resolution: "@sideway/pinpoint@npm:2.0.0" + checksum: 0f4491e5897fcf5bf02c46f5c359c56a314e90ba243f42f0c100437935daa2488f20482f0f77186bd6bf43345095a95d8143ecf8b1f4d876a7bc0806aba9c3d2 + languageName: node + linkType: hard + +"@sinclair/typebox@npm:^0.27.8": + version: 0.27.8 + resolution: "@sinclair/typebox@npm:0.27.8" + checksum: 00bd7362a3439021aa1ea51b0e0d0a0e8ca1351a3d54c606b115fdcc49b51b16db6e5f43b4fe7a28c38688523e22a94d49dd31168868b655f0d4d50f032d07a1 + languageName: node + linkType: hard + +"@sindresorhus/is@npm:^0.14.0": + version: 0.14.0 + resolution: "@sindresorhus/is@npm:0.14.0" + checksum: 971e0441dd44ba3909b467219a5e242da0fc584048db5324cfb8048148fa8dcc9d44d71e3948972c4f6121d24e5da402ef191420d1266a95f713bb6d6e59c98a + languageName: node + linkType: hard + +"@sindresorhus/is@npm:^4.6.0": + version: 4.6.0 + resolution: "@sindresorhus/is@npm:4.6.0" + checksum: 83839f13da2c29d55c97abc3bc2c55b250d33a0447554997a85c539e058e57b8da092da396e252b11ec24a0279a0bed1f537fa26302209327060643e327f81d2 + languageName: node + linkType: hard + +"@sindresorhus/is@npm:^5.2.0": + version: 5.6.0 + resolution: "@sindresorhus/is@npm:5.6.0" + checksum: 2e6e0c3acf188dcd9aea0f324ac1b6ad04c9fc672392a7b5a1218512fcde066965797eba8b9fe2108657a504388bd4a6664e6e6602555168e828a6df08b9f10e + languageName: node + linkType: hard + +"@sindresorhus/merge-streams@npm:^2.1.0": + version: 2.1.0 + resolution: "@sindresorhus/merge-streams@npm:2.1.0" + checksum: 8aa91a3fca68d4ba78f81cad80f2dc280fa82b6c49c9fa5fe37438b6b9082cf993adb2309163f924bef9d7173b2fae6bb40fc4070a344cbab8bcc19eb1ee0b7c + languageName: node + linkType: hard + +"@sinonjs/commons@npm:^2.0.0": + version: 2.0.0 + resolution: "@sinonjs/commons@npm:2.0.0" + dependencies: + type-detect: 4.0.8 + checksum: 5023ba17edf2b85ed58262313b8e9b59e23c6860681a9af0200f239fe939e2b79736d04a260e8270ddd57196851dde3ba754d7230be5c5234e777ae2ca8af137 + languageName: node + linkType: hard + +"@sinonjs/commons@npm:^3.0.0": + version: 3.0.0 + resolution: "@sinonjs/commons@npm:3.0.0" + dependencies: + type-detect: 4.0.8 + checksum: b4b5b73d4df4560fb8c0c7b38c7ad4aeabedd362f3373859d804c988c725889cde33550e4bcc7cd316a30f5152a2d1d43db71b6d0c38f5feef71fd8d016763f8 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^10.0.2": + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" + dependencies: + "@sinonjs/commons": ^3.0.0 + checksum: 614d30cb4d5201550c940945d44c9e0b6d64a888ff2cd5b357f95ad6721070d6b8839cd10e15b76bf5e14af0bcc1d8f9ec00d49a46318f1f669a4bec1d7f3148 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^11.2.2": + version: 11.2.2 + resolution: "@sinonjs/fake-timers@npm:11.2.2" + dependencies: + "@sinonjs/commons": ^3.0.0 + checksum: 68c29b0e1856fdc280df03ddbf57c726420b78e9f943a241b471edc018fb14ff36fdc1daafd6026cba08c3c7f50c976fb7ae11b88ff44cd7f609692ca7d25158 + languageName: node + linkType: hard + +"@sinonjs/samsam@npm:^8.0.0": + version: 8.0.0 + resolution: "@sinonjs/samsam@npm:8.0.0" + dependencies: + "@sinonjs/commons": ^2.0.0 + lodash.get: ^4.4.2 + type-detect: ^4.0.8 + checksum: 95e40d0bb9f7288e27c379bee1b03c3dc51e7e78b9d5ea6aef66a690da7e81efc4715145b561b449cefc5361a171791e3ce30fb1a46ab247d4c0766024c60a60 + languageName: node + linkType: hard + +"@sinonjs/text-encoding@npm:^0.7.1": + version: 0.7.2 + resolution: "@sinonjs/text-encoding@npm:0.7.2" + checksum: fe690002a32ba06906cf87e2e8fe84d1590294586f2a7fd180a65355b53660c155c3273d8011a5f2b77209b819aa7306678ae6e4aea0df014bd7ffd4bbbcf1ab + languageName: node + linkType: hard + +"@slorber/remark-comment@npm:^1.0.0": + version: 1.0.0 + resolution: "@slorber/remark-comment@npm:1.0.0" + dependencies: + micromark-factory-space: ^1.0.0 + micromark-util-character: ^1.1.0 + micromark-util-symbol: ^1.0.1 + checksum: c96f1533d09913c57381859966f10a706afd8eb680923924af1c451f3b72f22c31e394028d7535131c10f8682d3c60206da95c50fb4f016fbbd04218c853cc88 + languageName: node + linkType: hard + +"@slorber/static-site-generator-webpack-plugin@npm:^4.0.7": + version: 4.0.7 + resolution: "@slorber/static-site-generator-webpack-plugin@npm:4.0.7" + dependencies: + eval: ^0.1.8 + p-map: ^4.0.0 + webpack-sources: ^3.2.2 + checksum: a1e1d8b22dd51059524993f3fdd6861db10eb950debc389e5dd650702287fa2004eace03e6bc8f25b977bd7bc01d76a50aa271cbb73c58a8ec558945d728f307 + languageName: node + linkType: hard + +"@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3fc8e35d16f5abe0af5efe5851f27581225ac405d6a1ca44cda0df064cddfcc29a428c48c2e4bef6cebf627c9ac2f652a096030edb02cf5a120ce28d3c234710 + languageName: node + linkType: hard + +"@svgr/babel-plugin-add-jsx-attribute@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/babel-plugin-add-jsx-attribute@npm:6.5.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cab83832830a57735329ed68f67c03b57ca21fa037b0134847b0c5c0ef4beca89956d7dacfbf7b2a10fd901e7009e877512086db2ee918b8c69aee7742ae32c0 + languageName: node + linkType: hard + +"@svgr/babel-plugin-remove-jsx-attribute@npm:*, @svgr/babel-plugin-remove-jsx-attribute@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-remove-jsx-attribute@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ff992893c6c4ac802713ba3a97c13be34e62e6d981c813af40daabcd676df68a72a61bd1e692bb1eda3587f1b1d700ea462222ae2153bb0f46886632d4f88d08 + languageName: node + linkType: hard + +"@svgr/babel-plugin-remove-jsx-empty-expression@npm:*, @svgr/babel-plugin-remove-jsx-empty-expression@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-remove-jsx-empty-expression@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0fb691b63a21bac00da3aa2dccec50d0d5a5b347ff408d60803b84410d8af168f2656e4ba1ee1f24dab0ae4e4af77901f2928752bb0434c1f6788133ec599ec8 + languageName: node + linkType: hard + +"@svgr/babel-plugin-replace-jsx-attribute-value@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-replace-jsx-attribute-value@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 1edda65ef4f4dd8f021143c8ec276a08f6baa6f733b8e8ee2e7775597bf6b97afb47fdeefd579d6ae6c959fe2e634f55cd61d99377631212228c8cfb351b8921 + languageName: node + linkType: hard + +"@svgr/babel-plugin-replace-jsx-attribute-value@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/babel-plugin-replace-jsx-attribute-value@npm:6.5.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b7d2125758e766e1ebd14b92216b800bdc976959bc696dbfa1e28682919147c1df4bb8b1b5fd037d7a83026e27e681fea3b8d3741af8d3cf4c9dfa3d412125df + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-dynamic-title@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-svg-dynamic-title@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 876cec891488992e6a9aebb8155e2bea4ec461b4718c51de36e988e00e271c6d9d01ef6be17b9effd44b2b3d7db0b41c161a5904a46ae6f38b26b387ad7f3709 + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-dynamic-title@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/babel-plugin-svg-dynamic-title@npm:6.5.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0fd42ebf127ae9163ef341e84972daa99bdcb9e6ed3f83aabd95ee173fddc43e40e02fa847fbc0a1058cf5549f72b7960a2c5e22c3e4ac18f7e3ac81277852ae + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-em-dimensions@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-svg-em-dimensions@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: be0e2d391164428327d9ec469a52cea7d93189c6b0e2c290999e048f597d777852f701c64dca44cd45b31ed14a7f859520326e2e4ad7c3a4545d0aa235bc7e9a + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-em-dimensions@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/babel-plugin-svg-em-dimensions@npm:6.5.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c1550ee9f548526fa66fd171e3ffb5696bfc4e4cd108a631d39db492c7410dc10bba4eb5a190e9df824bf806130ccc586ae7d2e43c547e6a4f93bbb29a18f344 + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-react-native-svg@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/babel-plugin-transform-react-native-svg@npm:8.1.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 85b434a57572f53bd2b9f0606f253e1fcf57b4a8c554ec3f2d43ed17f50d8cae200cb3aaf1ec9d626e1456e8b135dce530ae047eb0bed6d4bf98a752d6640459 + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-react-native-svg@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/babel-plugin-transform-react-native-svg@npm:6.5.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4c924af22b948b812629e80efb90ad1ec8faae26a232d8ca8a06b46b53e966a2c415a57806a3ff0ea806a622612e546422719b69ec6839717a7755dac19171d9 + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-svg-component@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-transform-svg-component@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 04e2023d75693eeb0890341c40e449881184663056c249be7e5c80168e4aabb0fadd255e8d5d2dbf54b8c2a6e700efba994377135bfa4060dc4a2e860116ef8c + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-svg-component@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/babel-plugin-transform-svg-component@npm:6.5.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e496bb5ee871feb6bcab250b6e067322da7dd5c9c2b530b41e5586fe090f86611339b49d0a909c334d9b24cbca0fa755c949a2526c6ad03c6b5885666874cf5f + languageName: node + linkType: hard + +"@svgr/babel-preset@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/babel-preset@npm:8.1.0" + dependencies: + "@svgr/babel-plugin-add-jsx-attribute": 8.0.0 + "@svgr/babel-plugin-remove-jsx-attribute": 8.0.0 + "@svgr/babel-plugin-remove-jsx-empty-expression": 8.0.0 + "@svgr/babel-plugin-replace-jsx-attribute-value": 8.0.0 + "@svgr/babel-plugin-svg-dynamic-title": 8.0.0 + "@svgr/babel-plugin-svg-em-dimensions": 8.0.0 + "@svgr/babel-plugin-transform-react-native-svg": 8.1.0 + "@svgr/babel-plugin-transform-svg-component": 8.0.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3a67930f080b8891e1e8e2595716b879c944d253112bae763dce59807ba23454d162216c8d66a0a0e3d4f38a649ecd6c387e545d1e1261dd69a68e9a3392ee08 + languageName: node + linkType: hard + +"@svgr/babel-preset@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/babel-preset@npm:6.5.1" + dependencies: + "@svgr/babel-plugin-add-jsx-attribute": ^6.5.1 + "@svgr/babel-plugin-remove-jsx-attribute": "*" + "@svgr/babel-plugin-remove-jsx-empty-expression": "*" + "@svgr/babel-plugin-replace-jsx-attribute-value": ^6.5.1 + "@svgr/babel-plugin-svg-dynamic-title": ^6.5.1 + "@svgr/babel-plugin-svg-em-dimensions": ^6.5.1 + "@svgr/babel-plugin-transform-react-native-svg": ^6.5.1 + "@svgr/babel-plugin-transform-svg-component": ^6.5.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9f124be39a8e64f909162f925b3a63ddaa5a342a5e24fc0b7f7d9d4d7f7e3b916596c754fb557dc259928399cad5366a27cb231627a0d2dcc4b13ac521cf05af + languageName: node + linkType: hard + +"@svgr/core@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/core@npm:8.1.0" + dependencies: + "@babel/core": ^7.21.3 + "@svgr/babel-preset": 8.1.0 + camelcase: ^6.2.0 + cosmiconfig: ^8.1.3 + snake-case: ^3.0.4 + checksum: da4a12865c7dc59829d58df8bd232d6c85b7115fda40da0d2f844a1a51886e2e945560596ecfc0345d37837ac457de86a931e8b8d8550e729e0c688c02250d8a + languageName: node + linkType: hard + +"@svgr/core@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/core@npm:6.5.1" + dependencies: + "@babel/core": ^7.19.6 + "@svgr/babel-preset": ^6.5.1 + "@svgr/plugin-jsx": ^6.5.1 + camelcase: ^6.2.0 + cosmiconfig: ^7.0.1 + checksum: fd6d6d5da5aeb956703310480b626c1fb3e3973ad9fe8025efc1dcf3d895f857b70d100c63cf32cebb20eb83c9607bafa464c9436e18fe6fe4fafdc73ed6b1a5 + languageName: node + linkType: hard + +"@svgr/hast-util-to-babel-ast@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/hast-util-to-babel-ast@npm:8.0.0" + dependencies: + "@babel/types": ^7.21.3 + entities: ^4.4.0 + checksum: 88401281a38bbc7527e65ff5437970414391a86158ef4b4046c89764c156d2d39ecd7cce77be8a51994c9fb3249170cb1eb8b9128b62faaa81743ef6ed3534ab + languageName: node + linkType: hard + +"@svgr/hast-util-to-babel-ast@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/hast-util-to-babel-ast@npm:6.5.1" + dependencies: + "@babel/types": ^7.20.0 + entities: ^4.4.0 + checksum: 37923cce1b3f4e2039077b0c570b6edbabe37d1cf1a6ee35e71e0fe00f9cffac450eec45e9720b1010418131a999cb0047331ba1b6d1d2c69af1b92ac785aacf + languageName: node + linkType: hard + +"@svgr/plugin-jsx@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/plugin-jsx@npm:8.1.0" + dependencies: + "@babel/core": ^7.21.3 + "@svgr/babel-preset": 8.1.0 + "@svgr/hast-util-to-babel-ast": 8.0.0 + svg-parser: ^2.0.4 + peerDependencies: + "@svgr/core": "*" + checksum: 0418a9780753d3544912ee2dad5d2cf8d12e1ba74df8053651b3886aeda54d5f0f7d2dece0af5e0d838332c4f139a57f0dabaa3ca1afa4d1a765efce6a7656f2 + languageName: node + linkType: hard + +"@svgr/plugin-jsx@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/plugin-jsx@npm:6.5.1" + dependencies: + "@babel/core": ^7.19.6 + "@svgr/babel-preset": ^6.5.1 + "@svgr/hast-util-to-babel-ast": ^6.5.1 + svg-parser: ^2.0.4 + peerDependencies: + "@svgr/core": ^6.0.0 + checksum: 42f22847a6bdf930514d7bedd3c5e1fd8d53eb3594779f9db16cb94c762425907c375cd8ec789114e100a4d38068aca6c7ab5efea4c612fba63f0630c44cc859 + languageName: node + linkType: hard + +"@svgr/plugin-svgo@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/plugin-svgo@npm:8.1.0" + dependencies: + cosmiconfig: ^8.1.3 + deepmerge: ^4.3.1 + svgo: ^3.0.2 + peerDependencies: + "@svgr/core": "*" + checksum: 59d9d214cebaacca9ca71a561f463d8b7e5a68ca9443e4792a42d903acd52259b1790c0680bc6afecc3f00a255a6cbd7ea278a9f625bac443620ea58a590c2d0 + languageName: node + linkType: hard + +"@svgr/plugin-svgo@npm:^6.5.1": + version: 6.5.1 + resolution: "@svgr/plugin-svgo@npm:6.5.1" + dependencies: + cosmiconfig: ^7.0.1 + deepmerge: ^4.2.2 + svgo: ^2.8.0 + peerDependencies: + "@svgr/core": "*" + checksum: cd2833530ac0485221adc2146fd992ab20d79f4b12eebcd45fa859721dd779483158e11dfd9a534858fe468416b9412416e25cbe07ac7932c44ed5fa2021c72e + languageName: node + linkType: hard + +"@svgr/webpack@npm:^6.2.1": + version: 6.5.1 + resolution: "@svgr/webpack@npm:6.5.1" + dependencies: + "@babel/core": ^7.19.6 + "@babel/plugin-transform-react-constant-elements": ^7.18.12 + "@babel/preset-env": ^7.19.4 + "@babel/preset-react": ^7.18.6 + "@babel/preset-typescript": ^7.18.6 + "@svgr/core": ^6.5.1 + "@svgr/plugin-jsx": ^6.5.1 + "@svgr/plugin-svgo": ^6.5.1 + checksum: d10582eb4fa82a5b6d314cb49f2c640af4fd3a60f5b76095d2b14e383ef6a43a6f4674b68774a21787dbde69dec0a251cfcfc3f9a96c82754ba5d5c6daf785f0 + languageName: node + linkType: hard + +"@svgr/webpack@npm:^8.1.0": + version: 8.1.0 + resolution: "@svgr/webpack@npm:8.1.0" + dependencies: + "@babel/core": ^7.21.3 + "@babel/plugin-transform-react-constant-elements": ^7.21.3 + "@babel/preset-env": ^7.20.2 + "@babel/preset-react": ^7.18.6 + "@babel/preset-typescript": ^7.21.0 + "@svgr/core": 8.1.0 + "@svgr/plugin-jsx": 8.1.0 + "@svgr/plugin-svgo": 8.1.0 + checksum: c6eec5b0cf2fb2ecd3a7a362d272eda35330b17c76802a3481f499b5d07ff8f87b31d2571043bff399b051a1767b1e2e499dbf186104d1c06d76f9f1535fac01 + languageName: node + linkType: hard + +"@szmarczak/http-timer@npm:^1.1.2": + version: 1.1.2 + resolution: "@szmarczak/http-timer@npm:1.1.2" + dependencies: + defer-to-connect: ^1.0.1 + checksum: 4d9158061c5f397c57b4988cde33a163244e4f02df16364f103971957a32886beb104d6180902cbe8b38cb940e234d9f98a4e486200deca621923f62f50a06fe + languageName: node + linkType: hard + +"@szmarczak/http-timer@npm:^5.0.1": + version: 5.0.1 + resolution: "@szmarczak/http-timer@npm:5.0.1" + dependencies: + defer-to-connect: ^2.0.1 + checksum: fc9cb993e808806692e4a3337c90ece0ec00c89f4b67e3652a356b89730da98bc824273a6d67ca84d5f33cd85f317dcd5ce39d8cc0a2f060145a608a7cb8ce92 + languageName: node + linkType: hard + +"@tootallnate/quickjs-emscripten@npm:^0.23.0": + version: 0.23.0 + resolution: "@tootallnate/quickjs-emscripten@npm:0.23.0" + checksum: c350a2947ffb80b22e14ff35099fd582d1340d65723384a0fd0515e905e2534459ad2f301a43279a37308a27c99273c932e64649abd57d0bb3ca8c557150eccc + languageName: node + linkType: hard + +"@trysound/sax@npm:0.2.0": + version: 0.2.0 + resolution: "@trysound/sax@npm:0.2.0" + checksum: 11226c39b52b391719a2a92e10183e4260d9651f86edced166da1d95f39a0a1eaa470e44d14ac685ccd6d3df7e2002433782872c0feeb260d61e80f21250e65c + languageName: node + linkType: hard + +"@tsconfig/node10@npm:^1.0.7": + version: 1.0.9 + resolution: "@tsconfig/node10@npm:1.0.9" + checksum: a33ae4dc2a621c0678ac8ac4bceb8e512ae75dac65417a2ad9b022d9b5411e863c4c198b6ba9ef659e14b9fb609bbec680841a2e84c1172df7a5ffcf076539df + languageName: node + linkType: hard + +"@tsconfig/node12@npm:^1.0.7": + version: 1.0.11 + resolution: "@tsconfig/node12@npm:1.0.11" + checksum: 5ce29a41b13e7897a58b8e2df11269c5395999e588b9a467386f99d1d26f6c77d1af2719e407621412520ea30517d718d5192a32403b8dfcc163bf33e40a338a + languageName: node + linkType: hard + +"@tsconfig/node14@npm:^1.0.0": + version: 1.0.3 + resolution: "@tsconfig/node14@npm:1.0.3" + checksum: 19275fe80c4c8d0ad0abed6a96dbf00642e88b220b090418609c4376e1cef81bf16237bf170ad1b341452feddb8115d8dd2e5acdfdea1b27422071163dc9ba9d + languageName: node + linkType: hard + +"@tsconfig/node16@npm:^1.0.2": + version: 1.0.4 + resolution: "@tsconfig/node16@npm:1.0.4" + checksum: 202319785901f942a6e1e476b872d421baec20cf09f4b266a1854060efbf78cde16a4d256e8bc949d31e6cd9a90f1e8ef8fb06af96a65e98338a2b6b0de0a0ff + languageName: node + linkType: hard + +"@types/accepts@npm:*": + version: 1.3.7 + resolution: "@types/accepts@npm:1.3.7" + dependencies: + "@types/node": "*" + checksum: 7678cf74976e16093aff6e6f9755826faf069ac1e30179276158ce46ea246348ff22ca6bdd46cef08428881337d9ceefbf00bab08a7731646eb9fc9449d6a1e7 + languageName: node + linkType: hard + +"@types/acorn@npm:^4.0.0": + version: 4.0.6 + resolution: "@types/acorn@npm:4.0.6" + dependencies: + "@types/estree": "*" + checksum: 60e1fd28af18d6cb54a93a7231c7c18774a9a8739c9b179e9e8750dca631e10cbef2d82b02830ea3f557b1d121e6406441e9e1250bd492dc81d4b3456e76e4d4 + languageName: node + linkType: hard + +"@types/adm-zip@npm:^0.5.0": + version: 0.5.5 + resolution: "@types/adm-zip@npm:0.5.5" + dependencies: + "@types/node": "*" + checksum: 808c25b8a1c2e1c594cf9b1514e7953105cf96e19e38aa7dc109ff2537bda7345b950ef1f4e54a6e824e5503e29d24b0ff6d0aa1ff9bd4afb79ef0ef2df9ebab + languageName: node + linkType: hard + +"@types/babel__code-frame@npm:^7.0.2": + version: 7.0.6 + resolution: "@types/babel__code-frame@npm:7.0.6" + checksum: 5325ab85d95e58fe84279757788ddb0de68bfd6814bc636e868f9ff7b5229915873f28847c4baf48fd3a4a460a73b4ea87bc9e1d78a3a5a60cfc7ca627a722c5 + languageName: node + linkType: hard + +"@types/bn.js@npm:^4.11.3": + version: 4.11.6 + resolution: "@types/bn.js@npm:4.11.6" + dependencies: + "@types/node": "*" + checksum: 7f66f2c7b7b9303b3205a57184261974b114495736b77853af5b18d857c0b33e82ce7146911e86e87a87837de8acae28986716fd381ac7c301fd6e8d8b6c811f + languageName: node + linkType: hard + +"@types/bn.js@npm:^5.1.0": + version: 5.1.5 + resolution: "@types/bn.js@npm:5.1.5" + dependencies: + "@types/node": "*" + checksum: c87b28c4af74545624f8a3dae5294b16aa190c222626e8d4b2e327b33b1a3f1eeb43e7a24d914a9774bca43d8cd6e1cb0325c1f4b3a244af6693a024e1d918e6 + languageName: node + linkType: hard + +"@types/body-parser@npm:*": + version: 1.19.5 + resolution: "@types/body-parser@npm:1.19.5" + dependencies: + "@types/connect": "*" + "@types/node": "*" + checksum: 1e251118c4b2f61029cc43b0dc028495f2d1957fe8ee49a707fb940f86a9bd2f9754230805598278fe99958b49e9b7e66eec8ef6a50ab5c1f6b93e1ba2aaba82 + languageName: node + linkType: hard + +"@types/bonjour@npm:^3.5.13, @types/bonjour@npm:^3.5.9": + version: 3.5.13 + resolution: "@types/bonjour@npm:3.5.13" + dependencies: + "@types/node": "*" + checksum: e827570e097bd7d625a673c9c208af2d1a22fa3885c0a1646533cf24394c839c3e5f60ac1bc60c0ddcc69c0615078c9fb2c01b42596c7c582d895d974f2409ee + languageName: node + linkType: hard + +"@types/chai-as-promised@npm:^7.1.3": + version: 7.1.8 + resolution: "@types/chai-as-promised@npm:7.1.8" + dependencies: + "@types/chai": "*" + checksum: f0e5eab451b91bc1e289ed89519faf6591932e8a28d2ec9bbe95826eb73d28fe43713633e0c18706f3baa560a7d97e7c7c20dc53ce639e5d75bac46b2a50bf21 + languageName: node + linkType: hard + +"@types/chai@npm:*, @types/chai@npm:^4, @types/chai@npm:^4.2.12": + version: 4.3.11 + resolution: "@types/chai@npm:4.3.11" + checksum: d0c05fe5d02b2e6bbca2bd4866a2ab20a59cf729bc04af0060e7a3277eaf2fb65651b90d4c74b0ebf1d152b4b1d49fa8e44143acef276a2bbaa7785fbe5642d3 + languageName: node + linkType: hard + +"@types/co-body@npm:^6.1.0": + version: 6.1.3 + resolution: "@types/co-body@npm:6.1.3" + dependencies: + "@types/node": "*" + "@types/qs": "*" + checksum: e93fdc177f69ee0535cf401783258e4255f5eb8235c58b5a2a5a8958cf341fadf3d0bf2c75907ed6b7d188ce2c2f2cf9593a71d4eef12900beba54ebbbdd5cc1 + languageName: node + linkType: hard + +"@types/command-line-args@npm:^5.0.0": + version: 5.2.3 + resolution: "@types/command-line-args@npm:5.2.3" + checksum: 3d90db5b4bbaabd049654a0d12fa378989ab0d76a0f98d4c606761b5a08ce76458df0f9bb175219e187b4cd57e285e6f836d23e86b2c3d997820854cc3ed9121 + languageName: node + linkType: hard + +"@types/connect-history-api-fallback@npm:^1.3.5, @types/connect-history-api-fallback@npm:^1.5.4": + version: 1.5.4 + resolution: "@types/connect-history-api-fallback@npm:1.5.4" + dependencies: + "@types/express-serve-static-core": "*" + "@types/node": "*" + checksum: e1dee43b8570ffac02d2d47a2b4ba80d3ca0dd1840632dafb221da199e59dbe3778d3d7303c9e23c6b401f37c076935a5bc2aeae1c4e5feaefe1c371fe2073fd + languageName: node + linkType: hard + +"@types/connect@npm:*": + version: 3.4.38 + resolution: "@types/connect@npm:3.4.38" + dependencies: + "@types/node": "*" + checksum: 7eb1bc5342a9604facd57598a6c62621e244822442976c443efb84ff745246b10d06e8b309b6e80130026a396f19bf6793b7cecd7380169f369dac3bfc46fb99 + languageName: node + linkType: hard + +"@types/content-disposition@npm:*": + version: 0.5.8 + resolution: "@types/content-disposition@npm:0.5.8" + checksum: eeea868fb510ae7a32aa2d7de680fba79d59001f3e758a334621e10bc0a6496d3a42bb79243a5e53b9c63cb524522853ccc144fe1ab160c4247d37cdb81146c4 + languageName: node + linkType: hard + +"@types/convert-source-map@npm:^2.0.0": + version: 2.0.3 + resolution: "@types/convert-source-map@npm:2.0.3" + checksum: 411cf9a02cf5dbe204e325dd5ebf50de00b58b38d1d2a3064c6ea28417c23bae956206eaa9ed3a75a994909b4ab3f9c6389073d0636a62500fa6d6333c64d45a + languageName: node + linkType: hard + +"@types/cookies@npm:*": + version: 0.7.10 + resolution: "@types/cookies@npm:0.7.10" + dependencies: + "@types/connect": "*" + "@types/express": "*" + "@types/keygrip": "*" + "@types/node": "*" + checksum: 99cd44a193398932ff7926cfaac1eb4441d3dc47c3f64fdfb28861acbeb290b6db6a20376f993defc9d302db92bb1d36189b89ba447a633f960535f3f0d34e2d + languageName: node + linkType: hard + +"@types/debounce@npm:^1.2.0": + version: 1.2.4 + resolution: "@types/debounce@npm:1.2.4" + checksum: decef3eee65d681556d50f7fac346f1b33134f6b21f806d41326f9dfb362fa66b0282ff0640ae6791b690694c9dc3dad4e146e909e707e6f96650f3aa325b9da + languageName: node + linkType: hard + +"@types/debug@npm:^4.0.0": + version: 4.1.12 + resolution: "@types/debug@npm:4.1.12" + dependencies: + "@types/ms": "*" + checksum: 47876a852de8240bfdaf7481357af2b88cb660d30c72e73789abf00c499d6bc7cd5e52f41c915d1b9cd8ec9fef5b05688d7b7aef17f7f272c2d04679508d1053 + languageName: node + linkType: hard + +"@types/eslint-scope@npm:^3.7.3": + version: 3.7.7 + resolution: "@types/eslint-scope@npm:3.7.7" + dependencies: + "@types/eslint": "*" + "@types/estree": "*" + checksum: e2889a124aaab0b89af1bab5959847c5bec09809209255de0e63b9f54c629a94781daa04adb66bffcdd742f5e25a17614fb933965093c0eea64aacda4309380e + languageName: node + linkType: hard + +"@types/eslint@npm:*": + version: 8.44.8 + resolution: "@types/eslint@npm:8.44.8" + dependencies: + "@types/estree": "*" + "@types/json-schema": "*" + checksum: c3bc70166075e6e9f7fb43978882b9ac0b22596b519900b08dc8a1d761bbbddec4c48a60cc4eb674601266223c6f11db30f3fb6ceaae96c23c54b35ad88022bc + languageName: node + linkType: hard + +"@types/estree-jsx@npm:^1.0.0": + version: 1.0.3 + resolution: "@types/estree-jsx@npm:1.0.3" + dependencies: + "@types/estree": "*" + checksum: 6887a134308b6db4a33a147b56c9d0a47c17ea7e810bdd7c498c306a0fd00bcf2619cb0f57f74009d03dda974b3cd7e414767f85332b1d1b2be30a3ef9e1cca9 + languageName: node + linkType: hard + +"@types/estree@npm:*, @types/estree@npm:1.0.5, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a + 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" + dependencies: + "@types/node": "*" + "@types/qs": "*" + "@types/range-parser": "*" + "@types/send": "*" + checksum: 12750f6511dd870bbaccfb8208ad1e79361cf197b147f62a3bedc19ec642f3a0f9926ace96705f4bc88ec2ae56f61f7ca8c2438e6b22f5540842b5569c28a121 + languageName: node + linkType: hard + +"@types/express@npm:*, @types/express@npm:^4.17.13, @types/express@npm:^4.17.21": + version: 4.17.21 + resolution: "@types/express@npm:4.17.21" + dependencies: + "@types/body-parser": "*" + "@types/express-serve-static-core": ^4.17.33 + "@types/qs": "*" + "@types/serve-static": "*" + checksum: fb238298630370a7392c7abdc80f495ae6c716723e114705d7e3fb67e3850b3859bbfd29391463a3fb8c0b32051847935933d99e719c0478710f8098ee7091c5 + languageName: node + linkType: hard + +"@types/gtag.js@npm:^0.0.12": + version: 0.0.12 + resolution: "@types/gtag.js@npm:0.0.12" + checksum: 34efc27fbfd0013255b8bfd4af38ded9d5a6ba761130c76f17fd3a9585d83acc88d8005aab667cfec4bdec0e7c7217f689739799a8f61aed0edb929be58b162e + languageName: node + linkType: hard + +"@types/hast@npm:^2.0.0": + version: 2.3.8 + resolution: "@types/hast@npm:2.3.8" + dependencies: + "@types/unist": ^2 + checksum: 4c3b3efb7067d32a568a9bf5d2a7599f99ec08c2eaade3aaeb579b7a31bcdf8f6475f56c1ac5bc3f4e4e07b84a93a9b1cf1ef9a8b52b39e3deabea7989e5dd4b + languageName: node + linkType: hard + +"@types/hast@npm:^3.0.0": + version: 3.0.3 + resolution: "@types/hast@npm:3.0.3" + dependencies: + "@types/unist": "*" + checksum: ca204207550fd6848ee20b5ba2018fd54f515d59a8b80375cdbe392ba2b4b130dac25fdfbaf9f2a70d2aec9d074a34dc14d4d59d31fa3ede80ef9850afad5d3c + languageName: node + linkType: hard + +"@types/history@npm:^4.7.11": + version: 4.7.11 + resolution: "@types/history@npm:4.7.11" + checksum: c92e2ba407dcab0581a9afdf98f533aa41b61a71133420a6d92b1ca9839f741ab1f9395b17454ba5b88cb86020b70b22d74a1950ccfbdfd9beeaa5459fdc3464 + languageName: node + linkType: hard + +"@types/html-minifier-terser@npm:^6.0.0": + version: 6.1.0 + resolution: "@types/html-minifier-terser@npm:6.1.0" + checksum: eb843f6a8d662d44fb18ec61041117734c6aae77aa38df1be3b4712e8e50ffaa35f1e1c92fdd0fde14a5675fecf457abcd0d15a01fae7506c91926176967f452 + languageName: node + linkType: hard + +"@types/http-assert@npm:*": + version: 1.5.5 + resolution: "@types/http-assert@npm:1.5.5" + checksum: cd6bb7fd42cc6e2a702cb55370b8b25231954ad74c04bcd185b943a74ded3d4c28099c30f77b26951df2426441baff41718816c60b5af80efe2b8888d900bf93 + languageName: node + linkType: hard + +"@types/http-cache-semantics@npm:^4.0.2": + version: 4.0.4 + resolution: "@types/http-cache-semantics@npm:4.0.4" + checksum: 7f4dd832e618bc1e271be49717d7b4066d77c2d4eed5b81198eb987e532bb3e1c7e02f45d77918185bad936f884b700c10cebe06305f50400f382ab75055f9e8 + languageName: node + linkType: hard + +"@types/http-errors@npm:*": + version: 2.0.4 + resolution: "@types/http-errors@npm:2.0.4" + checksum: 1f3d7c3b32c7524811a45690881736b3ef741bf9849ae03d32ad1ab7062608454b150a4e7f1351f83d26a418b2d65af9bdc06198f1c079d75578282884c4e8e3 + languageName: node + linkType: hard + +"@types/http-proxy@npm:^1.17.8": + version: 1.17.14 + resolution: "@types/http-proxy@npm:1.17.14" + dependencies: + "@types/node": "*" + checksum: 491320bce3565bbb6c7d39d25b54bce626237cfb6b09e60ee7f77b56ae7c6cbad76f08d47fe01eaa706781124ee3dfad9bb737049254491efd98ed1f014c4e83 + languageName: node + linkType: hard + +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.3": + version: 2.0.6 + resolution: "@types/istanbul-lib-coverage@npm:2.0.6" + checksum: 3feac423fd3e5449485afac999dcfcb3d44a37c830af898b689fadc65d26526460bedb889db278e0d4d815a670331796494d073a10ee6e3a6526301fe7415778 + languageName: node + linkType: hard + +"@types/istanbul-lib-report@npm:*": + version: 3.0.3 + resolution: "@types/istanbul-lib-report@npm:3.0.3" + dependencies: + "@types/istanbul-lib-coverage": "*" + checksum: b91e9b60f865ff08cb35667a427b70f6c2c63e88105eadd29a112582942af47ed99c60610180aa8dcc22382fa405033f141c119c69b95db78c4c709fbadfeeb4 + languageName: node + linkType: hard + +"@types/istanbul-reports@npm:^3.0.0": + version: 3.0.4 + resolution: "@types/istanbul-reports@npm:3.0.4" + dependencies: + "@types/istanbul-lib-report": "*" + checksum: 93eb18835770b3431f68ae9ac1ca91741ab85f7606f310a34b3586b5a34450ec038c3eed7ab19266635499594de52ff73723a54a72a75b9f7d6a956f01edee95 + languageName: node + linkType: hard + +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 + languageName: node + linkType: hard + +"@types/katex@npm:^0.16.0": + version: 0.16.7 + resolution: "@types/katex@npm:0.16.7" + checksum: 4fd15d93553be97c02c064e16be18d7ccbabf66ec72a9dc7fd5bfa47f0c7581da2f942f693c7cb59499de4c843c2189796e49c9647d336cbd52b777b6722a95a + languageName: node + linkType: hard + +"@types/keygrip@npm:*": + version: 1.0.6 + resolution: "@types/keygrip@npm:1.0.6" + checksum: d157f60bf920492347791d2b26d530d5069ce05796549fbacd4c24d66ffbebbcb0ab67b21e7a1b80a593b9fd4b67dc4843dec04c12bbc2e0fddfb8577a826c41 + languageName: node + linkType: hard + +"@types/keyv@npm:^3.1.1": + version: 3.1.4 + resolution: "@types/keyv@npm:3.1.4" + dependencies: + "@types/node": "*" + checksum: e009a2bfb50e90ca9b7c6e8f648f8464067271fd99116f881073fa6fa76dc8d0133181dd65e6614d5fb1220d671d67b0124aef7d97dc02d7e342ab143a47779d + languageName: node + linkType: hard + +"@types/koa-compose@npm:*": + version: 3.2.8 + resolution: "@types/koa-compose@npm:3.2.8" + dependencies: + "@types/koa": "*" + checksum: 95c32bdee738ac7c10439bbf6342ca3b9f0aafd7e8118739eac7fb0fa703a23cfe4c88f63e13a69a16fbde702e0bcdc62b272aa734325fc8efa7e5625479752e + languageName: node + linkType: hard + +"@types/koa@npm:*, @types/koa@npm:^2.11.6": + version: 2.13.12 + resolution: "@types/koa@npm:2.13.12" + dependencies: + "@types/accepts": "*" + "@types/content-disposition": "*" + "@types/cookies": "*" + "@types/http-assert": "*" + "@types/http-errors": "*" + "@types/keygrip": "*" + "@types/koa-compose": "*" + "@types/node": "*" + checksum: 4a2e7e19bf91779d0a3c46b8838d6faba5ee0e9a888e5ef8683722c21aa8efcf35f86d1a661adb56ca9f239f7724e306055e33bfa1b2dc008b9c0fa9fcc12bee + languageName: node + linkType: hard + +"@types/lru-cache@npm:^5.1.0": + version: 5.1.1 + resolution: "@types/lru-cache@npm:5.1.1" + checksum: e1d6c0085f61b16ec5b3073ec76ad1be4844ea036561c3f145fc19f71f084b58a6eb600b14128aa95809d057d28f1d147c910186ae51219f58366ffd2ff2e118 + languageName: node + linkType: hard + +"@types/mdast@npm:^3.0.0": + version: 3.0.15 + resolution: "@types/mdast@npm:3.0.15" + dependencies: + "@types/unist": ^2 + checksum: af85042a4e3af3f879bde4059fa9e76c71cb552dffc896cdcc6cf9dc1fd38e37035c2dbd6245cfa6535b433f1f0478f5549696234ccace47a64055a10c656530 + languageName: node + linkType: hard + +"@types/mdast@npm:^4.0.0, @types/mdast@npm:^4.0.2": + version: 4.0.3 + resolution: "@types/mdast@npm:4.0.3" + dependencies: + "@types/unist": "*" + checksum: 345c5a22fccf05f35239ea6313ee4aaf6ebed5927c03ac79744abccb69b9ba5e692f9b771e36a012b79e17429082cada30f579e9c43b8a54e0ffb365431498b6 + languageName: node + linkType: hard + +"@types/mdx@npm:^2.0.0": + version: 2.0.10 + resolution: "@types/mdx@npm:2.0.10" + checksum: 3e2fb24b7bfae739a59573344171292b6c31256ad9afddc00232e9de4fbc97b270e1a11d13cb935cba0d9bbb9bc7348793eda82ee752233c5d2289f4b897f719 + languageName: node + linkType: hard + +"@types/mime@npm:*": + version: 3.0.4 + resolution: "@types/mime@npm:3.0.4" + checksum: a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843 + languageName: node + linkType: hard + +"@types/mime@npm:^1": + version: 1.3.5 + resolution: "@types/mime@npm:1.3.5" + checksum: e29a5f9c4776f5229d84e525b7cd7dd960b51c30a0fb9a028c0821790b82fca9f672dab56561e2acd9e8eed51d431bde52eafdfef30f643586c4162f1aecfc78 + languageName: node + linkType: hard + +"@types/mocha-each@npm:^2": + version: 2.0.4 + resolution: "@types/mocha-each@npm:2.0.4" + dependencies: + "@types/mocha": "*" + checksum: 2588284db079e2d0a17735c8fb5c12cba9feabf2de55c9ab49e1f3b38cc522691d30ed3abb1bcb21c087b27f373e3f4123ef7bd8d9a4f95cef38f6c8045c71f3 + languageName: node + linkType: hard + +"@types/mocha@npm:*, @types/mocha@npm:^10.0.1, @types/mocha@npm:^10.0.6": + version: 10.0.6 + resolution: "@types/mocha@npm:10.0.6" + checksum: f7c836cf6cf27dc0f5970d262591b56f2a3caeaec8cfdc612c12e1cfbb207f601f710ece207e935164d4e3343b93be5054d0db5544f31f453b3923775d82099f + languageName: node + linkType: hard + +"@types/ms@npm:*": + version: 0.7.34 + resolution: "@types/ms@npm:0.7.34" + checksum: f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a + languageName: node + linkType: hard + +"@types/node-forge@npm:^1.3.0": + version: 1.3.10 + resolution: "@types/node-forge@npm:1.3.10" + dependencies: + "@types/node": "*" + checksum: 363af42c83956c7e2483a71e398a02101ef6a55b4d86386c276315ca98bad02d6050b99fdbe13debcd1bcda250086b4a5b5c15a6fb2953d32420d269865ca7f8 + languageName: node + linkType: hard + +"@types/node@npm:*, @types/node@npm:^20.6.2": + version: 20.10.4 + resolution: "@types/node@npm:20.10.4" + dependencies: + undici-types: ~5.26.4 + checksum: 054b296417e771ab524bea63cf3289559c6bdf290d45428f7cc68e9b00030ff7a0ece47b8c99a26b4f47a443919813bcf42beadff2f0bea7d8125fa541d92eb0 + languageName: node + linkType: hard + +"@types/node@npm:18.15.13": + version: 18.15.13 + resolution: "@types/node@npm:18.15.13" + checksum: 79cc5a2b5f98e8973061a4260a781425efd39161a0e117a69cd089603964816c1a14025e1387b4590c8e82d05133b7b4154fa53a7dffb3877890a66145e76515 + languageName: node + linkType: hard + +"@types/node@npm:^17.0.5": + version: 17.0.45 + resolution: "@types/node@npm:17.0.45" + checksum: aa04366b9103b7d6cfd6b2ef64182e0eaa7d4462c3f817618486ea0422984c51fc69fd0d436eae6c9e696ddfdbec9ccaa27a917f7c2e8c75c5d57827fe3d95e8 + languageName: node + linkType: hard + +"@types/node@npm:^20.10.5": + version: 20.10.5 + resolution: "@types/node@npm:20.10.5" + dependencies: + undici-types: ~5.26.4 + checksum: e216b679f545a8356960ce985a0e53c3a58fff0eacd855e180b9e223b8db2b5bd07b744a002b8c1f0c37f9194648ab4578533b5c12df2ec10cc02f61d20948d2 + languageName: node + linkType: hard + +"@types/pako@npm:^2": + version: 2.0.3 + resolution: "@types/pako@npm:2.0.3" + checksum: 0746dd5d29eccf5b2e6cceb3ccb093851219e78bd2e2e20d25757e247987139e061e5d4ba37cb5295493f06e3c683c74f8876011cd8a3f3748a09244fbc841d9 + languageName: node + linkType: hard + +"@types/parse-json@npm:^4.0.0": + version: 4.0.2 + resolution: "@types/parse-json@npm:4.0.2" + checksum: 5bf62eec37c332ad10059252fc0dab7e7da730764869c980b0714777ad3d065e490627be9f40fc52f238ffa3ac4199b19de4127196910576c2fe34dd47c7a470 + languageName: node + linkType: hard + +"@types/parse5@npm:^5.0.0": + version: 5.0.3 + resolution: "@types/parse5@npm:5.0.3" + checksum: d6b7495cb1850f9f2e9c5e103ede9f2d30a5320669707b105c403868adc9e4bf8d3a7ff314cc23f67826bbbbbc0e6147346ce9062ab429f099dba7a01f463919 + languageName: node + linkType: hard + +"@types/parse5@npm:^6.0.1": + version: 6.0.3 + resolution: "@types/parse5@npm:6.0.3" + checksum: ddb59ee4144af5dfcc508a8dcf32f37879d11e12559561e65788756b95b33e6f03ea027d88e1f5408f9b7bfb656bf630ace31a2169edf44151daaf8dd58df1b7 + languageName: node + linkType: hard + +"@types/path-browserify@npm:^1": + version: 1.0.2 + resolution: "@types/path-browserify@npm:1.0.2" + checksum: 7b26df1a32827f7e588009386f62e0f900e8d349722b1b8b8c100cd2c4cc1e95c64099f5ec879cd131e69869088f336998a3ddb17085b68312414431a4eace01 + languageName: node + linkType: hard + +"@types/pbkdf2@npm:^3.0.0": + version: 3.1.2 + resolution: "@types/pbkdf2@npm:3.1.2" + dependencies: + "@types/node": "*" + checksum: bebe1e596cbbe5f7d2726a58859e61986c5a42459048e29cb7f2d4d764be6bbb0844572fd5d70ca8955a8a17e8b4ed80984fc4903e165d9efb8807a3fbb051aa + languageName: node + linkType: hard + +"@types/prettier@npm:^3": + version: 3.0.0 + resolution: "@types/prettier@npm:3.0.0" + dependencies: + prettier: "*" + checksum: a2a512d304e5bcf78f38089dc88ad19215e6ab871d435a17aef3ce538a63b07c0e359c18db23989dc1ed9fff96d99eee1f680416080184df5c7e0e3bf767e165 + languageName: node + linkType: hard + +"@types/prismjs@npm:^1.26.0": + version: 1.26.3 + resolution: "@types/prismjs@npm:1.26.3" + checksum: c627fa9d9f4277ce413bb8347944152cddfc892702e34ff4b099dc1cf3f00c09514d36349c23529b903b0e57f3b2e0dc91ee66e98af07fbbe1e3fe8346b23370 + languageName: node + linkType: hard + +"@types/prop-types@npm:*": + version: 15.7.11 + resolution: "@types/prop-types@npm:15.7.11" + checksum: 7519ff11d06fbf6b275029fe03fff9ec377b4cb6e864cac34d87d7146c7f5a7560fd164bdc1d2dbe00b60c43713631251af1fd3d34d46c69cd354602bc0c7c54 + languageName: node + linkType: hard + +"@types/qs@npm:*": + version: 6.9.10 + resolution: "@types/qs@npm:6.9.10" + checksum: 3e479ee056bd2b60894baa119d12ecd33f20a25231b836af04654e784c886f28a356477630430152a86fba253da65d7ecd18acffbc2a8877a336e75aa0272c67 + languageName: node + linkType: hard + +"@types/range-parser@npm:*": + version: 1.2.7 + resolution: "@types/range-parser@npm:1.2.7" + checksum: 95640233b689dfbd85b8c6ee268812a732cf36d5affead89e806fe30da9a430767af8ef2cd661024fd97e19d61f3dec75af2df5e80ec3bea000019ab7028629a + languageName: node + linkType: hard + +"@types/react-router-config@npm:*, @types/react-router-config@npm:^5.0.6, @types/react-router-config@npm:^5.0.7": + version: 5.0.11 + resolution: "@types/react-router-config@npm:5.0.11" + dependencies: + "@types/history": ^4.7.11 + "@types/react": "*" + "@types/react-router": ^5.1.0 + checksum: 4b72d9b71e0576e193c11e5085bbdac43f31debfa3b6ebc24666f3d646ef25c1f57f16c29b1ddd3051c881e85f8e0d4ab5a7bbd5fc215b9377f57675b210be7c + languageName: node + linkType: hard + +"@types/react-router-dom@npm:*": + version: 5.3.3 + resolution: "@types/react-router-dom@npm:5.3.3" + dependencies: + "@types/history": ^4.7.11 + "@types/react": "*" + "@types/react-router": "*" + checksum: 28c4ea48909803c414bf5a08502acbb8ba414669b4b43bb51297c05fe5addc4df0b8fd00e0a9d1e3535ec4073ef38aaafac2c4a2b95b787167d113bc059beff3 + languageName: node + linkType: hard + +"@types/react-router@npm:*, @types/react-router@npm:^5.1.0": + version: 5.1.20 + resolution: "@types/react-router@npm:5.1.20" + dependencies: + "@types/history": ^4.7.11 + "@types/react": "*" + checksum: 128764143473a5e9457ddc715436b5d49814b1c214dde48939b9bef23f0e77f52ffcdfa97eb8d3cc27e2c229869c0cdd90f637d887b62f2c9f065a87d6425419 + languageName: node + linkType: hard + +"@types/react@npm:*": + version: 18.2.43 + resolution: "@types/react@npm:18.2.43" + dependencies: + "@types/prop-types": "*" + "@types/scheduler": "*" + csstype: ^3.0.2 + checksum: e7e4da18c7b14e4b8b1ea630d1d8224835698f2bb2485766455bfb9dea93b8ee6cc549a9fe1cb10c984e62685db44fcfb61e8fac913b008cd30a92087f25b9df + languageName: node + linkType: hard + +"@types/readable-stream@npm:^4": + version: 4.0.10 + resolution: "@types/readable-stream@npm:4.0.10" + dependencies: + "@types/node": "*" + safe-buffer: ~5.1.1 + checksum: dc7cb95be737d442770fcaf1fbe3860c011f5f024c6f09c8b032f95b7ef9cce0031302715afe13e18d264b3a162e5838ce78873ec8d63eb238db49bc70906a21 + languageName: node + linkType: hard + +"@types/resolve@npm:1.20.2": + version: 1.20.2 + resolution: "@types/resolve@npm:1.20.2" + checksum: 61c2cad2499ffc8eab36e3b773945d337d848d3ac6b7b0a87c805ba814bc838ef2f262fc0f109bfd8d2e0898ff8bd80ad1025f9ff64f1f71d3d4294c9f14e5f6 + languageName: node + linkType: hard + +"@types/responselike@npm:^1.0.0": + version: 1.0.3 + resolution: "@types/responselike@npm:1.0.3" + dependencies: + "@types/node": "*" + checksum: 6ac4b35723429b11b117e813c7acc42c3af8b5554caaf1fc750404c1ae59f9b7376bc69b9e9e194a5a97357a597c2228b7173d317320f0360d617b6425212f58 + languageName: node + linkType: hard + +"@types/retry@npm:0.12.0": + version: 0.12.0 + resolution: "@types/retry@npm:0.12.0" + checksum: 61a072c7639f6e8126588bf1eb1ce8835f2cb9c2aba795c4491cf6310e013267b0c8488039857c261c387e9728c1b43205099223f160bb6a76b4374f741b5603 + languageName: node + linkType: hard + +"@types/retry@npm:0.12.2": + version: 0.12.2 + resolution: "@types/retry@npm:0.12.2" + checksum: e5675035717b39ce4f42f339657cae9637cf0c0051cf54314a6a2c44d38d91f6544be9ddc0280587789b6afd056be5d99dbe3e9f4df68c286c36321579b1bf4a + languageName: node + linkType: hard + +"@types/sax@npm:^1.2.1": + version: 1.2.7 + resolution: "@types/sax@npm:1.2.7" + dependencies: + "@types/node": "*" + checksum: 7ece5fbb5d9c8fc76ab0de2f99d705edf92f18e701d4f9d9b0647275e32eb65e656c1badf9dfaa12f4e1ff3e250561c8c9cfe79e8b5f33dd1417ac0f1804f6cc + languageName: node + linkType: hard + +"@types/scheduler@npm:*": + version: 0.16.8 + resolution: "@types/scheduler@npm:0.16.8" + checksum: 6c091b096daa490093bf30dd7947cd28e5b2cd612ec93448432b33f724b162587fed9309a0acc104d97b69b1d49a0f3fc755a62282054d62975d53d7fd13472d + languageName: node + linkType: hard + +"@types/secp256k1@npm:^4.0.1": + version: 4.0.6 + resolution: "@types/secp256k1@npm:4.0.6" + dependencies: + "@types/node": "*" + checksum: 984494caf49a4ce99fda2b9ea1840eb47af946b8c2737314108949bcc0c06b4880e871296bd49ed6ea4c8423e3a302ad79fec43abfc987330e7eb98f0c4e8ba4 + languageName: node + linkType: hard + +"@types/semver@npm:^7.5.0": + version: 7.5.6 + resolution: "@types/semver@npm:7.5.6" + checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 + languageName: node + linkType: hard + +"@types/send@npm:*": + version: 0.17.4 + resolution: "@types/send@npm:0.17.4" + dependencies: + "@types/mime": ^1 + "@types/node": "*" + checksum: cf4db48251bbb03cd6452b4de6e8e09e2d75390a92fd798eca4a803df06444adc94ed050246c94c7ed46fb97be1f63607f0e1f13c3ce83d71788b3e08640e5e0 + languageName: node + linkType: hard + +"@types/serve-index@npm:^1.9.1, @types/serve-index@npm:^1.9.4": + version: 1.9.4 + resolution: "@types/serve-index@npm:1.9.4" + dependencies: + "@types/express": "*" + checksum: 72727c88d54da5b13275ebfb75dcdc4aa12417bbe9da1939e017c4c5f0c906fae843aa4e0fbfe360e7ee9df2f3d388c21abfc488f77ce58693fb57809f8ded92 + languageName: node + linkType: hard + +"@types/serve-static@npm:*, @types/serve-static@npm:^1.13.10, @types/serve-static@npm:^1.15.5": + version: 1.15.5 + resolution: "@types/serve-static@npm:1.15.5" + dependencies: + "@types/http-errors": "*" + "@types/mime": "*" + "@types/node": "*" + checksum: 0ff4b3703cf20ba89c9f9e345bc38417860a88e85863c8d6fe274a543220ab7f5f647d307c60a71bb57dc9559f0890a661e8dc771a6ec5ef195d91c8afc4a893 + languageName: node + linkType: hard + +"@types/sinon@npm:^17": + version: 17.0.2 + resolution: "@types/sinon@npm:17.0.2" + dependencies: + "@types/sinonjs__fake-timers": "*" + checksum: 3a56615f2dc7d0b67d3e4b8ae358df2ff2164d89fabb22e9b46e6afe7d4df844a354ea65d409af9baf29ac0103ea562ab44dd0176405a9cf82a4ff183939f22f + languageName: node + linkType: hard + +"@types/sinonjs__fake-timers@npm:*": + version: 8.1.5 + resolution: "@types/sinonjs__fake-timers@npm:8.1.5" + checksum: 7e3c08f6c13df44f3ea7d9a5155ddf77e3f7314c156fa1c5a829a4f3763bafe2f75b1283b887f06e6b4296996a2f299b70f64ff82625f9af5885436e2524d10c + languageName: node + linkType: hard + +"@types/sockjs@npm:^0.3.33, @types/sockjs@npm:^0.3.36": + version: 0.3.36 + resolution: "@types/sockjs@npm:0.3.36" + dependencies: + "@types/node": "*" + checksum: b4b5381122465d80ea8b158537c00bc82317222d3fb31fd7229ff25b31fa89134abfbab969118da55622236bf3d8fee75759f3959908b5688991f492008f29bc + languageName: node + linkType: hard + +"@types/unist@npm:*, @types/unist@npm:^3.0.0": + version: 3.0.2 + resolution: "@types/unist@npm:3.0.2" + checksum: 3d04d0be69316e5f14599a0d993a208606c12818cf631fd399243d1dc7a9bd8a3917d6066baa6abc290814afbd744621484756803c80cba892c39cd4b4a85616 + languageName: node + linkType: hard + +"@types/unist@npm:^2, @types/unist@npm:^2.0.0, @types/unist@npm:^2.0.2, @types/unist@npm:^2.0.3": + version: 2.0.10 + resolution: "@types/unist@npm:2.0.10" + checksum: e2924e18dedf45f68a5c6ccd6015cd62f1643b1b43baac1854efa21ae9e70505db94290434a23da1137d9e31eb58e54ca175982005698ac37300a1c889f6c4aa + languageName: node + linkType: hard + +"@types/ws@npm:^7.4.0": + version: 7.4.7 + resolution: "@types/ws@npm:7.4.7" + dependencies: + "@types/node": "*" + checksum: b4c9b8ad209620c9b21e78314ce4ff07515c0cadab9af101c1651e7bfb992d7fd933bd8b9c99d110738fd6db523ed15f82f29f50b45510288da72e964dedb1a3 + languageName: node + linkType: hard + +"@types/ws@npm:^8.5.10, @types/ws@npm:^8.5.5": + version: 8.5.10 + resolution: "@types/ws@npm:8.5.10" + dependencies: + "@types/node": "*" + checksum: 3ec416ea2be24042ebd677932a462cf16d2080393d8d7d0b1b3f5d6eaa4a7387aaf0eefb99193c0bfd29444857cf2e0c3ac89899e130550dc6c14ada8a46d25e + languageName: node + linkType: hard + +"@types/yargs-parser@npm:*": + version: 21.0.3 + resolution: "@types/yargs-parser@npm:21.0.3" + checksum: ef236c27f9432983e91432d974243e6c4cdae227cb673740320eff32d04d853eed59c92ca6f1142a335cfdc0e17cccafa62e95886a8154ca8891cc2dec4ee6fc + languageName: node + linkType: hard + +"@types/yargs@npm:^17.0.8": + version: 17.0.32 + resolution: "@types/yargs@npm:17.0.32" + dependencies: + "@types/yargs-parser": "*" + checksum: 4505bdebe8716ff383640c6e928f855b5d337cb3c68c81f7249fc6b983d0aa48de3eee26062b84f37e0d75a5797bc745e0c6e76f42f81771252a758c638f36ba + languageName: node + linkType: hard + +"@types/yauzl@npm:^2.9.1": + version: 2.10.3 + resolution: "@types/yauzl@npm:2.10.3" + dependencies: + "@types/node": "*" + checksum: 5ee966ea7bd6b2802f31ad4281c92c4c0b6dfa593c378a2582c58541fa113bec3d70eb0696b34ad95e8e6861a884cba6c3e351285816693ed176222f840a8c08 + languageName: node + linkType: hard + +"@typescript-eslint/eslint-plugin@npm:^6.7.3": + version: 6.13.2 + resolution: "@typescript-eslint/eslint-plugin@npm:6.13.2" + dependencies: + "@eslint-community/regexpp": ^4.5.1 + "@typescript-eslint/scope-manager": 6.13.2 + "@typescript-eslint/type-utils": 6.13.2 + "@typescript-eslint/utils": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 + debug: ^4.3.4 + graphemer: ^1.4.0 + ignore: ^5.2.4 + natural-compare: ^1.4.0 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependencies: + "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: e50cbbe7104eecef59faf3355ab981d9f353b19327f0b4607dfd829b4726f9e694b536fe43ab55f50bb00fbfdd2e4268a7e2a568b28d5fcd0d2a32a8d2466218 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:^6.7.3": + version: 6.13.2 + resolution: "@typescript-eslint/parser@npm:6.13.2" + dependencies: + "@typescript-eslint/scope-manager": 6.13.2 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/typescript-estree": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 + debug: ^4.3.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: aeafc414d295d7855384f10d57abb4f5f2ff35b57991b5c8854f43268761b3cc995e62af585dea1dc48295d762f466b565b5ae5699bfe642585d3f83ba8e1515 + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/scope-manager@npm:6.13.2" + dependencies: + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 + checksum: ff8fd64ddf324e296e2e0e34a8f73149c9a5f14d1761ea8e8665fc5998faa2b0bbbd1a5d416aa10d725f13c804032d532f68e39a0ca6cc36d1c9b9c0aea94311 + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/type-utils@npm:6.13.2" + dependencies: + "@typescript-eslint/typescript-estree": 6.13.2 + "@typescript-eslint/utils": 6.13.2 + debug: ^4.3.4 + ts-api-utils: ^1.0.1 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: ba54e5746139f778c35e4058e523ec8c20b68cf6472b3a7784170328e48c228f0761d2fc7e43dab053ca7d85ac4378b6965567774e6afedf551e600638404215 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/types@npm:6.13.2" + checksum: 4493ff06fa07c68c5adbcbd842f6dd6f5c88f14d160b53c3379b6b703e6f62808fab7fdebcc06ff06a56f20ab432b6ceeb0afb8931dc97d4061cb417e787f2c1 + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/typescript-estree@npm:6.13.2" + dependencies: + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependenciesMeta: + typescript: + optional: true + checksum: 0c18ee5ef594a2411a788fe9d7bc6d51a03bce38d9d764bcb24ab557e5bc1942c2ddf9bd6fb4877eb102b0ae488974fb7b7fe72daa70a2054bf04d3cc6803546 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/utils@npm:6.13.2" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@types/json-schema": ^7.0.12 + "@types/semver": ^7.5.0 + "@typescript-eslint/scope-manager": 6.13.2 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/typescript-estree": 6.13.2 + semver: ^7.5.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + checksum: b66bcf2a945e9c55f3dccb48af49565863d974837ee23b2f01ce7f3fb2462eb8a5871784d4a2fcc80dac7d5cd4ed90c8d01431cd177c0249de89a448f6663fc8 + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/visitor-keys@npm:6.13.2" + dependencies: + "@typescript-eslint/types": 6.13.2 + eslint-visitor-keys: ^3.4.1 + checksum: 4b4def7acd7451e6a18dab3ee13f06504b3d23e51f195fced7c544f2203ee8a83426c82fa57ab6b58725c70fdedaf7a3eccb69793180be35756eed0f2c69fe04 + languageName: node + linkType: hard + +"@ungap/structured-clone@npm:^1.0.0, @ungap/structured-clone@npm:^1.2.0": + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 + languageName: node + linkType: hard + +"@wasm-tool/wasm-pack-plugin@npm:^1.7.0": + version: 1.7.0 + resolution: "@wasm-tool/wasm-pack-plugin@npm:1.7.0" + dependencies: + chalk: ^2.4.1 + command-exists: ^1.2.7 + watchpack: ^2.1.1 + which: ^2.0.2 + checksum: b0a09f70827b262c4b4689296aae712cc7d9fb742e32eb7e7b720a5b45be1d256864c84c37c8f97de4c762cdae9c35be4a37cdea6832281056921edf4944aea4 + languageName: node + linkType: hard + +"@web/browser-logs@npm:^0.4.0": + version: 0.4.0 + resolution: "@web/browser-logs@npm:0.4.0" + dependencies: + errorstacks: ^2.2.0 + checksum: 65c6c4312b1ff00ff40fd15c07708f5e113bb8b4f87c972356010546a0664287dd4f64c5475f8be27b6abb29b9272ecc4162aada90ffb732f1779ceec5fd8ad6 + languageName: node + linkType: hard + +"@web/config-loader@npm:^0.3.0": + version: 0.3.1 + resolution: "@web/config-loader@npm:0.3.1" + checksum: 3ff87dc5cf44a98be97477b1d4c36673d282e7567b61e554aff56f8674a187938c51cd8045f868ca5f4b6ff4d52c72fbbc176c26f27df4335f2341d105d2b535 + languageName: node + linkType: hard + +"@web/dev-server-core@npm:^0.4.1": + version: 0.4.1 + resolution: "@web/dev-server-core@npm:0.4.1" + dependencies: + "@types/koa": ^2.11.6 + "@types/ws": ^7.4.0 + "@web/parse5-utils": ^1.3.1 + chokidar: ^3.4.3 + clone: ^2.1.2 + es-module-lexer: ^1.0.0 + get-stream: ^6.0.0 + is-stream: ^2.0.0 + isbinaryfile: ^5.0.0 + koa: ^2.13.0 + koa-etag: ^4.0.0 + koa-send: ^5.0.1 + koa-static: ^5.0.0 + lru-cache: ^6.0.0 + mime-types: ^2.1.27 + parse5: ^6.0.1 + picomatch: ^2.2.2 + ws: ^7.4.2 + checksum: 4cf728ac781c7831c9c59ffaa1bd2dca1f1e8a6553bedd0d80e47d946ea427067eb1d07b028fc8296a36930c1dd5631e0bc1ccf8f0f4b9203da362c958c1833e + languageName: node + linkType: hard + +"@web/dev-server-core@npm:^0.7.0": + version: 0.7.0 + resolution: "@web/dev-server-core@npm:0.7.0" + dependencies: + "@types/koa": ^2.11.6 + "@types/ws": ^7.4.0 + "@web/parse5-utils": ^2.1.0 + chokidar: ^3.4.3 + clone: ^2.1.2 + es-module-lexer: ^1.0.0 + get-stream: ^6.0.0 + is-stream: ^2.0.0 + isbinaryfile: ^5.0.0 + koa: ^2.13.0 + koa-etag: ^4.0.0 + koa-send: ^5.0.1 + koa-static: ^5.0.0 + lru-cache: ^8.0.4 + mime-types: ^2.1.27 + parse5: ^6.0.1 + picomatch: ^2.2.2 + ws: ^7.4.2 + checksum: 68c4440c75eca686626182af94d40f8ffa2e7848074692abd930ae69490af1866c5d10f13e8ad6745fb7ae386ba91377b4bcdbd74604a9600ce4ab2c8df1576c + languageName: node + linkType: hard + +"@web/dev-server-esbuild@npm:^0.3.6": + version: 0.3.6 + resolution: "@web/dev-server-esbuild@npm:0.3.6" + dependencies: + "@mdn/browser-compat-data": ^4.0.0 + "@web/dev-server-core": ^0.4.1 + esbuild: ^0.16 || ^0.17 + parse5: ^6.0.1 + ua-parser-js: ^1.0.33 + checksum: ed29357d8a832c695f129de62bd658744b46b1e17a5aab24ad6d7cd09a90f27714d83fc6ece2471c35bff55f4f09435a18af65b37d65709019bfe09c10f4f9eb + languageName: node + linkType: hard + +"@web/dev-server-import-maps@npm:^0.2.0": + version: 0.2.0 + resolution: "@web/dev-server-import-maps@npm:0.2.0" + dependencies: + "@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 + picomatch: ^2.2.2 + checksum: 15dabfa385f023bab70758b80cc09443455830799793c1a404a7230d90ebf60e40984a10d8a6ceea2afb8f057e90a9f7356a76f867d5e5a2eeacbc397e41535a + languageName: node + linkType: hard + +"@web/dev-server-rollup@npm:^0.6.1": + version: 0.6.1 + resolution: "@web/dev-server-rollup@npm:0.6.1" + dependencies: + "@rollup/plugin-node-resolve": ^15.0.1 + "@web/dev-server-core": ^0.7.0 + nanocolors: ^0.2.1 + parse5: ^6.0.1 + rollup: ^4.4.0 + whatwg-url: ^11.0.0 + checksum: 59536e38d8519bc1edbf4e11adf36c4f5273c02f5fbc5171962cb7acadea2cfd8c44df057ff4422282f34964668280b3564f6b053bfee5327dc0368a382f2e00 + languageName: node + linkType: hard + +"@web/dev-server@npm:^0.4.0": + version: 0.4.1 + resolution: "@web/dev-server@npm:0.4.1" + dependencies: + "@babel/code-frame": ^7.12.11 + "@types/command-line-args": ^5.0.0 + "@web/config-loader": ^0.3.0 + "@web/dev-server-core": ^0.7.0 + "@web/dev-server-rollup": ^0.6.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: 2d9f2fcef4511e9965de24fef0ff4430a525ccc7bdc2069e51a96d1aaab4a50a935e32725dd128bb3641be4d6a2acb870f0d645208b59036bfd9d7f55c0a33a4 + languageName: node + linkType: hard + +"@web/parse5-utils@npm:^1.3.1": + version: 1.3.1 + resolution: "@web/parse5-utils@npm:1.3.1" + dependencies: + "@types/parse5": ^6.0.1 + parse5: ^6.0.1 + checksum: 3320b2c4ea1e6a2ff1e57086b0c697a71dac7a6e54da86b2fb8e6c1d5a673bf9b911a743a10daa8cd62a571719edf3e66c9b17e87d79cc982f234bf141e2e178 + languageName: node + linkType: hard + +"@web/parse5-utils@npm:^2.1.0": + version: 2.1.0 + resolution: "@web/parse5-utils@npm:2.1.0" + dependencies: + "@types/parse5": ^6.0.1 + parse5: ^6.0.1 + checksum: 0faa93c51d61934e0006bebc2e257036f8cedeb455c7bf22b8fdbc17919929518c2cc99ced3769f8eb3b1d6694dd4a7186d66ad2b3c4330140fd2ce03dc6c4d2 + languageName: node + linkType: hard + +"@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: ^22.0.0 + checksum: 99cfa93d12e8854fb2d104de1f8c5a73403e39fc56e5ed78e24f63e903299521750c7b475253dfb75293a2e604ed83d5cfdc1e593a72e9208a99a511bdb6169a + languageName: node + linkType: hard + +"@web/test-runner-commands@npm:^0.9.0": + version: 0.9.0 + resolution: "@web/test-runner-commands@npm:0.9.0" + dependencies: + "@web/test-runner-core": ^0.13.0 + mkdirp: ^1.0.4 + checksum: df226f76148c5967df68c2589549b10ffe75f3d34a31d63bea132447271cdf073de7350aa680fcbf4315737b909fc44faad23d9f8e7e3ce37e93e05e67a7f295 + languageName: node + linkType: hard + +"@web/test-runner-core@npm:^0.13.0": + version: 0.13.0 + resolution: "@web/test-runner-core@npm:0.13.0" + 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.4.0 + "@web/dev-server-core": ^0.7.0 + 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.1 + 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: 6c2bd4962da51521dc0d2cf660bf4e1fa3a9a92166a8c71e85a9fe9160710bbe83658dfceae6108123dcf85bf41fbabd8d3b7294f350e2f732f3713fcaa9a024 + languageName: node + linkType: hard + +"@web/test-runner-coverage-v8@npm:^0.8.0": + version: 0.8.0 + resolution: "@web/test-runner-coverage-v8@npm:0.8.0" + dependencies: + "@web/test-runner-core": ^0.13.0 + istanbul-lib-coverage: ^3.0.0 + lru-cache: ^8.0.4 + picomatch: ^2.2.2 + v8-to-istanbul: ^9.0.1 + checksum: 343f834372b3aeb2c24f4b03ce956d8ad851ef2a85b94507651c2a65321fcdff1b26a2c44d7516e97d9c42786bb003b9c245ad0798a414a814d0264fdbe0761e + 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" + dependencies: + "@web/test-runner-core": ^0.13.0 + checksum: bcc9410ac9d679e7bb804fc5720b2a0ed3b4d08f2b49c03f2157f5b54c7f525a432712e1da644f04e5190c2480af2dc46a4c736cdba3fda3ba5fa98fd0f01a94 + languageName: node + linkType: hard + +"@web/test-runner-playwright@npm:^0.11.0": + version: 0.11.0 + resolution: "@web/test-runner-playwright@npm:0.11.0" + dependencies: + "@web/test-runner-core": ^0.13.0 + "@web/test-runner-coverage-v8": ^0.8.0 + playwright: ^1.22.2 + checksum: 3618b0b559d865af1211b3d86ec57487b32722a0dd640c9a3faca6c692cceec75176d742d0db73c823d300fbe761e5c15b2fad0c5096c3dbfedab313ed1aa7fe + languageName: node + linkType: hard + +"@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.16.0 + "@web/test-runner-commands": ^0.9.0 + "@web/test-runner-core": ^0.13.0 + "@web/test-runner-mocha": ^0.9.0 + 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: eb21fc5978da2ccbfd6ffac0f61b519036d68a9cdcf211c1dbafa9c6b6f92bb10a9267dec02f4d71dfc45e636166d98712ff9a347af951eabff99b0d7e5899b5 + languageName: node + linkType: hard + +"@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/ast@npm:1.11.6" + dependencies: + "@webassemblyjs/helper-numbers": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + checksum: 38ef1b526ca47c210f30975b06df2faf1a8170b1636ce239fc5738fc231ce28389dd61ecedd1bacfc03cbe95b16d1af848c805652080cb60982836eb4ed2c6cf + languageName: node + linkType: hard + +"@webassemblyjs/floating-point-hex-parser@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.6" + checksum: 29b08758841fd8b299c7152eda36b9eb4921e9c584eb4594437b5cd90ed6b920523606eae7316175f89c20628da14326801090167cc7fbffc77af448ac84b7e2 + languageName: node + linkType: hard + +"@webassemblyjs/helper-api-error@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-api-error@npm:1.11.6" + checksum: e8563df85161096343008f9161adb138a6e8f3c2cc338d6a36011aa55eabb32f2fd138ffe63bc278d009ada001cc41d263dadd1c0be01be6c2ed99076103689f + languageName: node + linkType: hard + +"@webassemblyjs/helper-buffer@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-buffer@npm:1.11.6" + checksum: b14d0573bf680d22b2522e8a341ec451fddd645d1f9c6bd9012ccb7e587a2973b86ab7b89fe91e1c79939ba96095f503af04369a3b356c8023c13a5893221644 + languageName: node + linkType: hard + +"@webassemblyjs/helper-numbers@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-numbers@npm:1.11.6" + dependencies: + "@webassemblyjs/floating-point-hex-parser": 1.11.6 + "@webassemblyjs/helper-api-error": 1.11.6 + "@xtuc/long": 4.2.2 + checksum: f4b562fa219f84368528339e0f8d273ad44e047a07641ffcaaec6f93e5b76fd86490a009aa91a294584e1436d74b0a01fa9fde45e333a4c657b58168b04da424 + languageName: node + linkType: hard + +"@webassemblyjs/helper-wasm-bytecode@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.6" + checksum: 3535ef4f1fba38de3475e383b3980f4bbf3de72bbb631c2b6584c7df45be4eccd62c6ff48b5edd3f1bcff275cfd605a37679ec199fc91fd0a7705d7f1e3972dc + languageName: node + linkType: hard + +"@webassemblyjs/helper-wasm-section@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.6" + dependencies: + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/wasm-gen": 1.11.6 + checksum: b2cf751bf4552b5b9999d27bbb7692d0aca75260140195cb58ea6374d7b9c2dc69b61e10b211a0e773f66209c3ddd612137ed66097e3684d7816f854997682e9 + languageName: node + linkType: hard + +"@webassemblyjs/ieee754@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/ieee754@npm:1.11.6" + dependencies: + "@xtuc/ieee754": ^1.2.0 + checksum: 13574b8e41f6ca39b700e292d7edf102577db5650fe8add7066a320aa4b7a7c09a5056feccac7a74eb68c10dea9546d4461412af351f13f6b24b5f32379b49de + languageName: node + linkType: hard + +"@webassemblyjs/leb128@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/leb128@npm:1.11.6" + dependencies: + "@xtuc/long": 4.2.2 + checksum: 7ea942dc9777d4b18a5ebfa3a937b30ae9e1d2ce1fee637583ed7f376334dd1d4274f813d2e250056cca803e0952def4b954913f1a3c9068bcd4ab4ee5143bf0 + languageName: node + linkType: hard + +"@webassemblyjs/utf8@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/utf8@npm:1.11.6" + checksum: 807fe5b5ce10c390cfdd93e0fb92abda8aebabb5199980681e7c3743ee3306a75729bcd1e56a3903980e96c885ee53ef901fcbaac8efdfa480f9c0dae1d08713 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-edit@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-edit@npm:1.11.6" + dependencies: + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/helper-wasm-section": 1.11.6 + "@webassemblyjs/wasm-gen": 1.11.6 + "@webassemblyjs/wasm-opt": 1.11.6 + "@webassemblyjs/wasm-parser": 1.11.6 + "@webassemblyjs/wast-printer": 1.11.6 + checksum: 29ce75870496d6fad864d815ebb072395a8a3a04dc9c3f4e1ffdc63fc5fa58b1f34304a1117296d8240054cfdbc38aca88e71fb51483cf29ffab0a61ef27b481 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-gen@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-gen@npm:1.11.6" + dependencies: + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/ieee754": 1.11.6 + "@webassemblyjs/leb128": 1.11.6 + "@webassemblyjs/utf8": 1.11.6 + checksum: a645a2eecbea24833c3260a249704a7f554ef4a94c6000984728e94bb2bc9140a68dfd6fd21d5e0bbb09f6dfc98e083a45760a83ae0417b41a0196ff6d45a23a + languageName: node + linkType: hard + +"@webassemblyjs/wasm-opt@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-opt@npm:1.11.6" + dependencies: + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-buffer": 1.11.6 + "@webassemblyjs/wasm-gen": 1.11.6 + "@webassemblyjs/wasm-parser": 1.11.6 + checksum: b4557f195487f8e97336ddf79f7bef40d788239169aac707f6eaa2fa5fe243557c2d74e550a8e57f2788e70c7ae4e7d32f7be16101afe183d597b747a3bdd528 + languageName: node + linkType: hard + +"@webassemblyjs/wasm-parser@npm:1.11.6, @webassemblyjs/wasm-parser@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-parser@npm:1.11.6" + dependencies: + "@webassemblyjs/ast": 1.11.6 + "@webassemblyjs/helper-api-error": 1.11.6 + "@webassemblyjs/helper-wasm-bytecode": 1.11.6 + "@webassemblyjs/ieee754": 1.11.6 + "@webassemblyjs/leb128": 1.11.6 + "@webassemblyjs/utf8": 1.11.6 + checksum: 8200a8d77c15621724a23fdabe58d5571415cda98a7058f542e670ea965dd75499f5e34a48675184947c66f3df23adf55df060312e6d72d57908e3f049620d8a + languageName: node + linkType: hard + +"@webassemblyjs/wast-printer@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wast-printer@npm:1.11.6" + dependencies: + "@webassemblyjs/ast": 1.11.6 + "@xtuc/long": 4.2.2 + checksum: d2fa6a4c427325ec81463e9c809aa6572af6d47f619f3091bf4c4a6fc34f1da3df7caddaac50b8e7a457f8784c62cd58c6311b6cb69b0162ccd8d4c072f79cf8 + languageName: node + linkType: hard + +"@webpack-cli/configtest@npm:^2.1.1": + version: 2.1.1 + resolution: "@webpack-cli/configtest@npm:2.1.1" + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + checksum: 9f9f9145c2d05471fc83d426db1df85cf49f329836b0c4b9f46b6948bed4b013464c00622b136d2a0a26993ce2306976682592245b08ee717500b1db45009a72 + languageName: node + linkType: hard + +"@webpack-cli/info@npm:^2.0.2": + version: 2.0.2 + resolution: "@webpack-cli/info@npm:2.0.2" + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + checksum: 8f9a178afca5c82e113aed1efa552d64ee5ae4fdff63fe747c096a981ec74f18a5d07bd6e89bbe6715c3e57d96eea024a410e58977169489fe1df044c10dd94e + languageName: node + linkType: hard + +"@webpack-cli/serve@npm:^2.0.5": + version: 2.0.5 + resolution: "@webpack-cli/serve@npm:2.0.5" + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + peerDependenciesMeta: + webpack-dev-server: + optional: true + checksum: 75f0e54681796d567a71ac3e2781d2901a8d8cf1cdfc82f261034dddac59a8343e8c3bc5e32b4bb9d6766759ba49fb29a5cd86ef1701d79c506fe886bb63ac75 + languageName: node + linkType: hard + +"@xtuc/ieee754@npm:^1.2.0": + version: 1.2.0 + resolution: "@xtuc/ieee754@npm:1.2.0" + checksum: ac56d4ca6e17790f1b1677f978c0c6808b1900a5b138885d3da21732f62e30e8f0d9120fcf8f6edfff5100ca902b46f8dd7c1e3f903728634523981e80e2885a + languageName: node + linkType: hard + +"@xtuc/long@npm:4.2.2": + version: 4.2.2 + resolution: "@xtuc/long@npm:4.2.2" + checksum: 8ed0d477ce3bc9c6fe2bf6a6a2cc316bb9c4127c5a7827bae947fa8ec34c7092395c5a283cc300c05b5fa01cbbfa1f938f410a7bf75db7c7846fea41949989ec + languageName: node + linkType: hard + +"@zeit/schemas@npm:2.29.0": + version: 2.29.0 + resolution: "@zeit/schemas@npm:2.29.0" + checksum: 3cea06bb67d790336aca0cc17580fd492ff3fc66ef4d180dce7053ff7ff54ab81b56bf718ba6f537148c581161d06306a481ec218d540bff922e0e009844ffd1 + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 0e994ad2aa6575f94670d8a2149afe94465de9cedaaaac364e7fb43a40c3691c980ff74899f682f4ca58fa96b4cbd7421a015d3a6defe43a442117d7821a2f36 + languageName: node + linkType: hard + +"abort-controller@npm:^3.0.0": + version: 3.0.0 + resolution: "abort-controller@npm:3.0.0" + dependencies: + event-target-shim: ^5.0.0 + checksum: 170bdba9b47b7e65906a28c8ce4f38a7a369d78e2271706f020849c1bfe0ee2067d4261df8bbb66eb84f79208fd5b710df759d64191db58cfba7ce8ef9c54b75 + languageName: node + linkType: hard + +"abstract-leveldown@npm:~0.12.0, abstract-leveldown@npm:~0.12.1": + version: 0.12.4 + resolution: "abstract-leveldown@npm:0.12.4" + dependencies: + xtend: ~3.0.0 + checksum: e300f04bb638cc9c462f6e8fa925672e51beb24c1470c39ece709e54f2f499661ac5fe0119175c7dcb6e32c843423d6960009d4d24e72526478b261163e8070b + languageName: node + linkType: hard + +"accepts@npm:^1.3.5, accepts@npm:~1.3.4, accepts@npm:~1.3.5, accepts@npm:~1.3.8": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: ~2.1.34 + negotiator: 0.6.3 + checksum: 50c43d32e7b50285ebe84b613ee4a3aa426715a7d131b65b786e2ead0fd76b6b60091b9916d3478a75f11f162628a2139991b6c03ab3f1d9ab7c86075dc8eab4 + languageName: node + linkType: hard + +"acorn-import-assertions@npm:^1.9.0": + version: 1.9.0 + resolution: "acorn-import-assertions@npm:1.9.0" + peerDependencies: + acorn: ^8 + checksum: 944fb2659d0845c467066bdcda2e20c05abe3aaf11972116df457ce2627628a81764d800dd55031ba19de513ee0d43bb771bc679cc0eda66dc8b4fade143bc0c + languageName: node + linkType: hard + +"acorn-jsx@npm:^5.0.0, acorn-jsx@npm:^5.3.2": + version: 5.3.2 + resolution: "acorn-jsx@npm:5.3.2" + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: c3d3b2a89c9a056b205b69530a37b972b404ee46ec8e5b341666f9513d3163e2a4f214a71f4dfc7370f5a9c07472d2fd1c11c91c3f03d093e37637d95da98950 + languageName: node + linkType: hard + +"acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.1.1": + version: 8.3.1 + resolution: "acorn-walk@npm:8.3.1" + checksum: 5c8926ddb5400bc825b6baca782931f9df4ace603ba1a517f5243290fd9cdb089d52877840687b5d5c939591ebc314e2e63721514feaa37c6829c828f2b940ce + languageName: node + linkType: hard + +"acorn@npm:^8.0.0, acorn@npm:^8.0.4, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.11.2 + resolution: "acorn@npm:8.11.2" + bin: + acorn: bin/acorn + checksum: 818450408684da89423e3daae24e4dc9b68692db8ab49ea4569c7c5abb7a3f23669438bf129cc81dfdada95e1c9b944ee1bfca2c57a05a4dc73834a612fbf6a7 + languageName: node + linkType: hard + +"address@npm:^1.0.1, address@npm:^1.1.2": + version: 1.2.2 + resolution: "address@npm:1.2.2" + checksum: ace439960c1e3564d8f523aff23a841904bf33a2a7c2e064f7f60a064194075758b9690e65bd9785692a4ef698a998c57eb74d145881a1cecab8ba658ddb1607 + languageName: node + linkType: hard + +"adm-zip@npm:^0.4.16": + version: 0.4.16 + resolution: "adm-zip@npm:0.4.16" + checksum: 5ea46664d8b3b073fffeb7f934705fea288708745e708cffc1dd732ce3d2672cecd476b243f9d051892fd12952db2b6bd061975e1ff40057246f6d0cb6534a50 + languageName: node + linkType: hard + +"adm-zip@npm:^0.5.0": + version: 0.5.10 + resolution: "adm-zip@npm:0.5.10" + checksum: 07ed91cf6423bf5dca4ee63977bc7635e91b8d21829c00829d48dce4c6932e1b19e6cfcbe44f1931c956e68795ae97183fc775913883fa48ce88a1ac11fb2034 + languageName: node + linkType: hard + +"aes-js@npm:4.0.0-beta.5": + version: 4.0.0-beta.5 + resolution: "aes-js@npm:4.0.0-beta.5" + checksum: cc2ea969d77df939c32057f7e361b6530aa6cb93cb10617a17a45cd164e6d761002f031ff6330af3e67e58b1f0a3a8fd0b63a720afd591a653b02f649470e15b + languageName: node + linkType: hard + +"agent-base@npm:6": + version: 6.0.2 + resolution: "agent-base@npm:6.0.2" + dependencies: + debug: 4 + checksum: f52b6872cc96fd5f622071b71ef200e01c7c4c454ee68bc9accca90c98cfb39f2810e3e9aa330435835eedc8c23f4f8a15267f67c6e245d2b33757575bdac49d + languageName: node + linkType: hard + +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": + version: 7.1.0 + resolution: "agent-base@npm:7.1.0" + dependencies: + debug: ^4.3.4 + checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: ^2.0.0 + indent-string: ^4.0.0 + checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 + languageName: node + linkType: hard + +"ajv-formats@npm:^2.1.1": + version: 2.1.1 + resolution: "ajv-formats@npm:2.1.1" + dependencies: + ajv: ^8.0.0 + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + checksum: 4a287d937f1ebaad4683249a4c40c0fa3beed30d9ddc0adba04859026a622da0d317851316ea64b3680dc60f5c3c708105ddd5d5db8fe595d9d0207fd19f90b7 + languageName: node + linkType: hard + +"ajv-keywords@npm:^3.4.1, ajv-keywords@npm:^3.5.2": + version: 3.5.2 + resolution: "ajv-keywords@npm:3.5.2" + peerDependencies: + ajv: ^6.9.1 + checksum: 7dc5e5931677a680589050f79dcbe1fefbb8fea38a955af03724229139175b433c63c68f7ae5f86cf8f65d55eb7c25f75a046723e2e58296707617ca690feae9 + languageName: node + linkType: hard + +"ajv-keywords@npm:^5.1.0": + version: 5.1.0 + resolution: "ajv-keywords@npm:5.1.0" + dependencies: + fast-deep-equal: ^3.1.3 + peerDependencies: + ajv: ^8.8.2 + checksum: c35193940b853119242c6757787f09ecf89a2c19bcd36d03ed1a615e710d19d450cb448bfda407b939aba54b002368c8bff30529cc50a0536a8e10bcce300421 + languageName: node + linkType: hard + +"ajv@npm:8.11.0": + version: 8.11.0 + resolution: "ajv@npm:8.11.0" + dependencies: + fast-deep-equal: ^3.1.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + uri-js: ^4.2.2 + checksum: 5e0ff226806763be73e93dd7805b634f6f5921e3e90ca04acdf8db81eed9d8d3f0d4c5f1213047f45ebbf8047ffe0c840fa1ef2ec42c3a644899f69aa72b5bef + languageName: node + linkType: hard + +"ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5": + version: 6.12.6 + resolution: "ajv@npm:6.12.6" + dependencies: + fast-deep-equal: ^3.1.1 + fast-json-stable-stringify: ^2.0.0 + json-schema-traverse: ^0.4.1 + uri-js: ^4.2.2 + checksum: 874972efe5c4202ab0a68379481fbd3d1b5d0a7bd6d3cc21d40d3536ebff3352a2a1fabb632d4fd2cc7fe4cbdcd5ed6782084c9bbf7f32a1536d18f9da5007d4 + languageName: node + linkType: hard + +"ajv@npm:^8.0.0, ajv@npm:^8.9.0": + version: 8.12.0 + resolution: "ajv@npm:8.12.0" + dependencies: + fast-deep-equal: ^3.1.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + uri-js: ^4.2.2 + checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001 + languageName: node + linkType: hard + +"algoliasearch-helper@npm:^3.13.3": + version: 3.16.0 + resolution: "algoliasearch-helper@npm:3.16.0" + dependencies: + "@algolia/events": ^4.0.1 + peerDependencies: + algoliasearch: ">= 3.1 < 6" + checksum: e024ad33c65d1eb7a31290bcf0bec37f2485154364e90ada45e07242ac35155313fe913fabd08cdb4d69e2794cc7d09dda03878566cea286cfac8fd4cc61f33f + languageName: node + linkType: hard + +"algoliasearch@npm:^4.18.0, algoliasearch@npm:^4.19.1": + version: 4.20.0 + resolution: "algoliasearch@npm:4.20.0" + dependencies: + "@algolia/cache-browser-local-storage": 4.20.0 + "@algolia/cache-common": 4.20.0 + "@algolia/cache-in-memory": 4.20.0 + "@algolia/client-account": 4.20.0 + "@algolia/client-analytics": 4.20.0 + "@algolia/client-common": 4.20.0 + "@algolia/client-personalization": 4.20.0 + "@algolia/client-search": 4.20.0 + "@algolia/logger-common": 4.20.0 + "@algolia/logger-console": 4.20.0 + "@algolia/requester-browser-xhr": 4.20.0 + "@algolia/requester-common": 4.20.0 + "@algolia/requester-node-http": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: 078954944452f57d2e3b47c6ed4905caf797814324a4d5068a8b6685d434a885977a3e607714c5fb6eb29c7c3e717b3ee9cb01c8b2320e2c7bd73bcd8d42e70f + languageName: node + linkType: hard + +"ansi-align@npm:^3.0.0, ansi-align@npm:^3.0.1": + version: 3.0.1 + resolution: "ansi-align@npm:3.0.1" + dependencies: + string-width: ^4.1.0 + checksum: 6abfa08f2141d231c257162b15292467081fa49a208593e055c866aa0455b57f3a86b5a678c190c618faa79b4c59e254493099cb700dd9cf2293c6be2c8f5d8d + languageName: node + linkType: hard + +"ansi-colors@npm:4.1.1": + version: 4.1.1 + resolution: "ansi-colors@npm:4.1.1" + checksum: 138d04a51076cb085da0a7e2d000c5c0bb09f6e772ed5c65c53cb118d37f6c5f1637506d7155fb5f330f0abcf6f12fa2e489ac3f8cdab9da393bf1bb4f9a32b0 + languageName: node + linkType: hard + +"ansi-colors@npm:^4.1.1": + version: 4.1.3 + resolution: "ansi-colors@npm:4.1.3" + checksum: a9c2ec842038a1fabc7db9ece7d3177e2fe1c5dc6f0c51ecfbf5f39911427b89c00b5dc6b8bd95f82a26e9b16aaae2e83d45f060e98070ce4d1333038edceb0e + languageName: node + linkType: hard + +"ansi-escapes@npm:^4.3.0": + version: 4.3.2 + resolution: "ansi-escapes@npm:4.3.2" + dependencies: + type-fest: ^0.21.3 + checksum: 93111c42189c0a6bed9cdb4d7f2829548e943827ee8479c74d6e0b22ee127b2a21d3f8b5ca57723b8ef78ce011fbfc2784350eb2bde3ccfccf2f575fa8489815 + languageName: node + linkType: hard + +"ansi-html-community@npm:^0.0.8": + version: 0.0.8 + resolution: "ansi-html-community@npm:0.0.8" + bin: + ansi-html: bin/ansi-html + checksum: 04c568e8348a636963f915e48eaa3e01218322e1169acafdd79c384f22e5558c003f79bbc480c1563865497482817c7eed025f0653ebc17642fededa5cb42089 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + languageName: node + linkType: hard + +"ansi-sequence-parser@npm:^1.1.0": + version: 1.1.1 + resolution: "ansi-sequence-parser@npm:1.1.1" + checksum: ead5b15c596e8e85ca02951a844366c6776769dcc9fd1bd3a0db11bb21364554822c6a439877fb599e7e1ffa0b5f039f1e5501423950457f3dcb2f480c30b188 + languageName: node + linkType: hard + +"ansi-styles@npm:^3.2.1": + version: 3.2.1 + resolution: "ansi-styles@npm:3.2.1" + dependencies: + color-convert: ^1.9.0 + checksum: d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: ^2.0.1 + checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 + languageName: node + linkType: hard + +"anymatch@npm:~3.1.2": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: ^3.0.0 + picomatch: ^2.0.4 + checksum: 3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 + languageName: node + linkType: hard + +"arch@npm:^2.2.0": + version: 2.2.0 + resolution: "arch@npm:2.2.0" + checksum: e21b7635029fe8e9cdd5a026f9a6c659103e63fff423834323cdf836a1bb240a72d0c39ca8c470f84643385cf581bd8eda2cad8bf493e27e54bd9783abe9101f + languageName: node + linkType: hard + +"arg@npm:5.0.2, arg@npm:^5.0.0, arg@npm:^5.0.2": + version: 5.0.2 + resolution: "arg@npm:5.0.2" + checksum: 6c69ada1a9943d332d9e5382393e897c500908d91d5cb735a01120d5f71daf1b339b7b8980cbeaba8fd1afc68e658a739746179e4315a26e8a28951ff9930078 + languageName: node + linkType: hard + +"arg@npm:^4.1.0": + version: 4.1.3 + resolution: "arg@npm:4.1.3" + checksum: 544af8dd3f60546d3e4aff084d451b96961d2267d668670199692f8d054f0415d86fc5497d0e641e91546f0aa920e7c29e5250e99fc89f5552a34b5d93b77f43 + languageName: node + linkType: hard + +"argparse@npm:^1.0.7": + version: 1.0.10 + resolution: "argparse@npm:1.0.10" + dependencies: + sprintf-js: ~1.0.2 + checksum: 7ca6e45583a28de7258e39e13d81e925cfa25d7d4aacbf806a382d3c02fcb13403a07fb8aeef949f10a7cfe4a62da0e2e807b348a5980554cc28ee573ef95945 + languageName: node + linkType: hard + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 83644b56493e89a254bae05702abf3a1101b4fa4d0ca31df1c9985275a5a5bd47b3c27b7fa0b71098d41114d8ca000e6ed90cad764b306f8a503665e4d517ced + languageName: node + linkType: hard + +"array-back@npm:^3.0.1, array-back@npm:^3.1.0": + version: 3.1.0 + resolution: "array-back@npm:3.1.0" + checksum: 7205004fcd0f9edd926db921af901b083094608d5b265738d0290092f9822f73accb468e677db74c7c94ef432d39e5ed75a7b1786701e182efb25bbba9734209 + languageName: node + linkType: hard + +"array-back@npm:^4.0.1, array-back@npm:^4.0.2": + version: 4.0.2 + resolution: "array-back@npm:4.0.2" + checksum: f30603270771eeb54e5aad5f54604c62b3577a18b6db212a7272b2b6c32049121b49431f656654790ed1469411e45f387e7627c0de8fd0515995cc40df9b9294 + languageName: node + linkType: hard + +"array-back@npm:^6.2.2": + version: 6.2.2 + resolution: "array-back@npm:6.2.2" + checksum: baae1e3a1687300a307d3bdf09715f6415e1099b5729d3d8e397309fb1e43d90b939d694602892172aaca7e0aeed38da89d04aa4951637d31c2a21350809e003 + languageName: node + linkType: hard + +"array-flatten@npm:1.1.1": + version: 1.1.1 + resolution: "array-flatten@npm:1.1.1" + checksum: a9925bf3512d9dce202112965de90c222cd59a4fbfce68a0951d25d965cf44642931f40aac72309c41f12df19afa010ecadceb07cfff9ccc1621e99d89ab5f3b + languageName: node + linkType: hard + +"array-flatten@npm:^2.1.2": + version: 2.1.2 + resolution: "array-flatten@npm:2.1.2" + checksum: e8988aac1fbfcdaae343d08c9a06a6fddd2c6141721eeeea45c3cf523bf4431d29a46602929455ed548c7a3e0769928cdc630405427297e7081bd118fdec9262 + languageName: node + linkType: hard + +"array-timsort@npm:^1.0.3": + version: 1.0.3 + resolution: "array-timsort@npm:1.0.3" + checksum: fd4b5b0911214bdc8b5699ed10d309685551b518b3819c611c967cff59b87aee01cf591a10e36a3f14dbff696984bd6682b845f6fdbf1217195e910f241a4f78 + languageName: node + linkType: hard + +"array-union@npm:^2.1.0": + version: 2.1.0 + resolution: "array-union@npm:2.1.0" + checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d + languageName: node + linkType: hard + +"assert@npm:^2.1.0": + version: 2.1.0 + resolution: "assert@npm:2.1.0" + dependencies: + call-bind: ^1.0.2 + is-nan: ^1.3.2 + object-is: ^1.1.5 + object.assign: ^4.1.4 + util: ^0.12.5 + checksum: 1ed1cabba9abe55f4109b3f7292b4e4f3cf2953aad8dc148c0b3c3bd676675c31b1abb32ef563b7d5a19d1715bf90d1e5f09fad2a4ee655199468902da80f7c2 + languageName: node + linkType: hard + +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf + languageName: node + linkType: hard + +"ast-types@npm:^0.13.4": + version: 0.13.4 + resolution: "ast-types@npm:0.13.4" + dependencies: + tslib: ^2.0.1 + checksum: 5a51f7b70588ecced3601845a0e203279ca2f5fdc184416a0a1640c93ec0a267241d6090a328e78eebb8de81f8754754e0a4f1558ba2a3d638f8ccbd0b1f0eff + languageName: node + linkType: hard + +"astral-regex@npm:^2.0.0": + version: 2.0.0 + resolution: "astral-regex@npm:2.0.0" + checksum: 876231688c66400473ba505731df37ea436e574dd524520294cc3bbc54ea40334865e01fa0d074d74d036ee874ee7e62f486ea38bc421ee8e6a871c06f011766 + languageName: node + linkType: hard + +"astring@npm:^1.8.0": + version: 1.8.6 + resolution: "astring@npm:1.8.6" + bin: + astring: bin/astring + checksum: 6f034d2acef1dac8bb231e7cc26c573d3c14e1975ea6e04f20312b43d4f462f963209bc64187d25d477a182dc3c33277959a0156ab7a3617aa79b1eac4d88e1f + languageName: node + linkType: hard + +"async-mutex@npm:0.4.0": + version: 0.4.0 + resolution: "async-mutex@npm:0.4.0" + dependencies: + tslib: ^2.4.0 + checksum: 813a71728b35a4fbfd64dba719f04726d9133c67b577fcd951b7028c4a675a13ee34e69beb82d621f87bf81f5d4f135c4c44be0448550c7db728547244ef71fc + languageName: node + linkType: hard + +"async@npm:^2.6.4": + version: 2.6.4 + resolution: "async@npm:2.6.4" + dependencies: + lodash: ^4.17.14 + checksum: a52083fb32e1ebe1d63e5c5624038bb30be68ff07a6c8d7dfe35e47c93fc144bd8652cbec869e0ac07d57dde387aa5f1386be3559cdee799cb1f789678d88e19 + languageName: node + linkType: hard + +"asynckit@npm:^0.4.0": + version: 0.4.0 + resolution: "asynckit@npm:0.4.0" + checksum: 7b78c451df768adba04e2d02e63e2d0bf3b07adcd6e42b4cf665cb7ce899bedd344c69a1dcbce355b5f972d597b25aaa1c1742b52cffd9caccb22f348114f6be + languageName: node + linkType: hard + +"at-least-node@npm:^1.0.0": + version: 1.0.0 + resolution: "at-least-node@npm:1.0.0" + checksum: 463e2f8e43384f1afb54bc68485c436d7622acec08b6fad269b421cb1d29cebb5af751426793d0961ed243146fe4dc983402f6d5a51b720b277818dbf6f2e49e + languageName: node + linkType: hard + +"autoprefixer@npm:^10.4.12, autoprefixer@npm:^10.4.14, autoprefixer@npm:^10.4.7": + version: 10.4.16 + resolution: "autoprefixer@npm:10.4.16" + dependencies: + browserslist: ^4.21.10 + caniuse-lite: ^1.0.30001538 + fraction.js: ^4.3.6 + normalize-range: ^0.1.2 + picocolors: ^1.0.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.1.0 + bin: + autoprefixer: bin/autoprefixer + checksum: 45fad7086495048dacb14bb7b00313e70e135b5d8e8751dcc60548889400763705ab16fc2d99ea628b44c3472698fb0e39598f595ba28409c965ab159035afde + languageName: node + linkType: hard + +"autoprefixer@npm:^10.4.19": + version: 10.4.20 + resolution: "autoprefixer@npm:10.4.20" + dependencies: + browserslist: ^4.23.3 + caniuse-lite: ^1.0.30001646 + fraction.js: ^4.3.7 + normalize-range: ^0.1.2 + picocolors: ^1.0.1 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.1.0 + bin: + autoprefixer: bin/autoprefixer + checksum: 187cec2ec356631932b212f76dc64f4419c117fdb2fb9eeeb40867d38ba5ca5ba734e6ceefc9e3af4eec8258e60accdf5cbf2b7708798598fde35cdc3de562d6 + languageName: node + linkType: hard + +"available-typed-arrays@npm:^1.0.5": + version: 1.0.5 + resolution: "available-typed-arrays@npm:1.0.5" + checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a + languageName: node + linkType: hard + +"axios@npm:^0.25.0": + version: 0.25.0 + resolution: "axios@npm:0.25.0" + dependencies: + follow-redirects: ^1.14.7 + checksum: 2a8a3787c05f2a0c9c3878f49782357e2a9f38945b93018fb0c4fd788171c43dceefbb577988628e09fea53952744d1ecebde234b561f1e703aa43e0a598a3ad + languageName: node + linkType: hard + +"axios@npm:^1.4.0": + version: 1.6.2 + resolution: "axios@npm:1.6.2" + dependencies: + follow-redirects: ^1.15.0 + form-data: ^4.0.0 + proxy-from-env: ^1.1.0 + checksum: 4a7429e2b784be0f2902ca2680964391eae7236faa3967715f30ea45464b98ae3f1c6f631303b13dfe721b17126b01f486c7644b9ef276bfc63112db9fd379f8 + languageName: node + linkType: hard + +"b4a@npm:^1.6.4": + version: 1.6.4 + resolution: "b4a@npm:1.6.4" + checksum: 81b086f9af1f8845fbef4476307236bda3d660c158c201db976f19cdce05f41f93110ab6b12fd7a2696602a490cc43d5410ee36a56d6eef93afb0d6ca69ac3b2 + languageName: node + linkType: hard + +"babel-loader@npm:^8.2.5": + version: 8.3.0 + resolution: "babel-loader@npm:8.3.0" + dependencies: + find-cache-dir: ^3.3.1 + loader-utils: ^2.0.0 + make-dir: ^3.1.0 + schema-utils: ^2.6.5 + peerDependencies: + "@babel/core": ^7.0.0 + webpack: ">=2" + checksum: d48bcf9e030e598656ad3ff5fb85967db2eaaf38af5b4a4b99d25618a2057f9f100e6b231af2a46c1913206db506115ca7a8cbdf52c9c73d767070dae4352ab5 + languageName: node + linkType: hard + +"babel-loader@npm:^9.1.3": + version: 9.1.3 + resolution: "babel-loader@npm:9.1.3" + dependencies: + find-cache-dir: ^4.0.0 + schema-utils: ^4.0.0 + peerDependencies: + "@babel/core": ^7.12.0 + webpack: ">=5" + checksum: b168dde5b8cf11206513371a79f86bb3faa7c714e6ec9fffd420876b61f3d7f5f4b976431095ef6a14bc4d324505126deb91045fd41e312ba49f4deaa166fe28 + languageName: node + linkType: hard + +"babel-plugin-apply-mdx-type-prop@npm:1.6.22": + version: 1.6.22 + resolution: "babel-plugin-apply-mdx-type-prop@npm:1.6.22" + dependencies: + "@babel/helper-plugin-utils": 7.10.4 + "@mdx-js/util": 1.6.22 + peerDependencies: + "@babel/core": ^7.11.6 + checksum: 43e2100164a8f3e46fddd76afcbfb1f02cbebd5612cfe63f3d344a740b0afbdc4d2bf5659cffe9323dd2554c7b86b23ebedae9dadcec353b6594f4292a1a28e2 + languageName: node + linkType: hard + +"babel-plugin-dynamic-import-node@npm:^2.3.3": + version: 2.3.3 + resolution: "babel-plugin-dynamic-import-node@npm:2.3.3" + dependencies: + object.assign: ^4.1.0 + checksum: c9d24415bcc608d0db7d4c8540d8002ac2f94e2573d2eadced137a29d9eab7e25d2cbb4bc6b9db65cf6ee7430f7dd011d19c911a9a778f0533b4a05ce8292c9b + languageName: node + linkType: hard + +"babel-plugin-extract-import-names@npm:1.6.22": + version: 1.6.22 + resolution: "babel-plugin-extract-import-names@npm:1.6.22" + dependencies: + "@babel/helper-plugin-utils": 7.10.4 + checksum: 145ccf09c96d36411d340e78086555f8d4d5924ea39fcb0eca461c066cfa98bc4344982bb35eb85d054ef88f8d4dfc0205ba27370c1d8fcc78191b02908d044d + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs2@npm:^0.4.10": + version: 0.4.11 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.11" + dependencies: + "@babel/compat-data": ^7.22.6 + "@babel/helper-define-polyfill-provider": ^0.6.2 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: f098353ce7c7dde1a1d2710858e01b471e85689110c9e37813e009072347eb8c55d5f84d20d3bf1cab31755f20078ba90f8855fdc4686a9daa826a95ff280bd7 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs2@npm:^0.4.6": + version: 0.4.6 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.6" + dependencies: + "@babel/compat-data": ^7.22.6 + "@babel/helper-define-polyfill-provider": ^0.4.3 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 08896811df31530be6a9bcdd630cb9fd4b5ae5181039d18db3796efbc54e38d57a42af460845c10a04434e1bc45c0d47743c7e6c860383cc6b141083cde22030 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs3@npm:^0.10.6": + version: 0.10.6 + resolution: "babel-plugin-polyfill-corejs3@npm:0.10.6" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.6.2 + core-js-compat: ^3.38.0 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: f762f29f7acca576897c63149c850f0a72babd3fb9ea436a2e36f0c339161c4b912a77828541d8188ce8a91e50965c6687120cf36071eabb1b7aa92f279e2164 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs3@npm:^0.8.5": + version: 0.8.6 + resolution: "babel-plugin-polyfill-corejs3@npm:0.8.6" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.4.3 + core-js-compat: ^3.33.1 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 36951c2edac42ac0f05b200502e90d77bf66ccee5b52e2937d23496c6ef2372cce31b8c64144da374b77bd3eb65e2721703a52eac56cad16a152326c092cbf77 + languageName: node + linkType: hard + +"babel-plugin-polyfill-regenerator@npm:^0.5.3": + version: 0.5.3 + resolution: "babel-plugin-polyfill-regenerator@npm:0.5.3" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.4.3 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 2bb546582cda1870d19e646a7183baeb2cccd56e0ef3e4eaeabd28e120daf17cb87399194a9ccdcf32506bcaa68d23e73440fc8ab990a7a0f8c5a77c12d5d4bc + languageName: node + linkType: hard + +"babel-plugin-polyfill-regenerator@npm:^0.6.1": + version: 0.6.2 + resolution: "babel-plugin-polyfill-regenerator@npm:0.6.2" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.6.2 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 150233571072b6b3dfe946242da39cba8587b7f908d1c006f7545fc88b0e3c3018d445739beb61e7a75835f0c2751dbe884a94ff9b245ec42369d9267e0e1b3f + languageName: node + linkType: hard + +"bail@npm:^1.0.0": + version: 1.0.5 + resolution: "bail@npm:1.0.5" + checksum: 6c334940d7eaa4e656a12fb12407b6555649b6deb6df04270fa806e0da82684ebe4a4e47815b271c794b40f8d6fa286e0c248b14ddbabb324a917fab09b7301a + languageName: node + linkType: hard + +"bail@npm:^2.0.0": + version: 2.0.2 + resolution: "bail@npm:2.0.2" + checksum: aab4e8ccdc8d762bf3fdfce8e706601695620c0c2eda256dd85088dc0be3cfd7ff126f6e99c2bee1f24f5d418414aacf09d7f9702f16d6963df2fa488cda8824 + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 + 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" + dependencies: + safe-buffer: ^5.0.1 + checksum: 957101d6fd09e1903e846fd8f69fd7e5e3e50254383e61ab667c725866bec54e5ece5ba49ce385128ae48f9ec93a26567d1d5ebb91f4d56ef4a9cc0d5a5481e8 + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 + languageName: node + linkType: hard + +"basic-ftp@npm:^5.0.2": + version: 5.0.4 + resolution: "basic-ftp@npm:5.0.4" + checksum: 57725f24debd8c1b36f9bad1bfee39c5d9f5997f32a23e5c957389dcc64373a13b41711e5723b4a3b616a93530b345686119f480c27a115b2fde944c1652ceb1 + languageName: node + linkType: hard + +"batch@npm:0.6.1": + version: 0.6.1 + resolution: "batch@npm:0.6.1" + checksum: 61f9934c7378a51dce61b915586191078ef7f1c3eca707fdd58b96ff2ff56d9e0af2bdab66b1462301a73c73374239e6542d9821c0af787f3209a23365d07e7f + languageName: node + linkType: hard + +"big.js@npm:^5.2.2": + version: 5.2.2 + resolution: "big.js@npm:5.2.2" + checksum: b89b6e8419b097a8fb4ed2399a1931a68c612bce3cfd5ca8c214b2d017531191070f990598de2fc6f3f993d91c0f08aa82697717f6b3b8732c9731866d233c9e + languageName: node + linkType: hard + +"binary-extensions@npm:^2.0.0": + version: 2.2.0 + resolution: "binary-extensions@npm:2.2.0" + checksum: ccd267956c58d2315f5d3ea6757cf09863c5fc703e50fbeb13a7dc849b812ef76e3cf9ca8f35a0c48498776a7478d7b4a0418e1e2b8cb9cb9731f2922aaad7f8 + languageName: node + linkType: hard + +"bl@npm:~0.8.1": + version: 0.8.2 + resolution: "bl@npm:0.8.2" + dependencies: + readable-stream: ~1.0.26 + checksum: 18767c5c861ae1cdbb000bb346e9e8e29137225e8eef97f39db78beeb236beca609f465580c5c1b177d621505f57400834fb4a17a66d264f33a0237293ec2ac5 + languageName: node + linkType: hard + +"blakejs@npm:^1.1.0": + version: 1.2.1 + resolution: "blakejs@npm:1.2.1" + checksum: d699ba116cfa21d0b01d12014a03e484dd76d483133e6dc9eb415aa70a119f08beb3bcefb8c71840106a00b542cba77383f8be60cd1f0d4589cb8afb922eefbe + languageName: node + linkType: hard + +"bn.js@npm:^4.11.0, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9": + version: 4.12.0 + resolution: "bn.js@npm:4.12.0" + checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12 + languageName: node + linkType: hard + +"bn.js@npm:^5.2.0, bn.js@npm:^5.2.1": + version: 5.2.1 + resolution: "bn.js@npm:5.2.1" + checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 + languageName: node + linkType: hard + +"body-parser@npm:1.20.1": + version: 1.20.1 + resolution: "body-parser@npm:1.20.1" + dependencies: + bytes: 3.1.2 + content-type: ~1.0.4 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: ~1.6.18 + unpipe: 1.0.0 + checksum: f1050dbac3bede6a78f0b87947a8d548ce43f91ccc718a50dd774f3c81f2d8b04693e52acf62659fad23101827dd318da1fb1363444ff9a8482b886a3e4a5266 + languageName: node + linkType: hard + +"bonjour-service@npm:^1.0.11": + version: 1.1.1 + resolution: "bonjour-service@npm:1.1.1" + dependencies: + array-flatten: ^2.1.2 + dns-equal: ^1.0.0 + fast-deep-equal: ^3.1.3 + multicast-dns: ^7.2.5 + checksum: 832d0cf78b91368fac8bb11fd7a714e46f4c4fb1bb14d7283bce614a6fb3aae2f3fe209aba5b4fa051811c1cab6921d073a83db8432fb23292f27dd4161fb0f1 + languageName: node + linkType: hard + +"bonjour-service@npm:^1.2.1": + version: 1.2.1 + resolution: "bonjour-service@npm:1.2.1" + dependencies: + fast-deep-equal: ^3.1.3 + multicast-dns: ^7.2.5 + checksum: b65b3e6e3a07e97f2da5806afb76f3946d5a6426b72e849a0236dc3c9d3612fb8c5359ebade4be7eb63f74a37670c53a53be2ff17f4f709811fda77f600eb25b + languageName: node + linkType: hard + +"boolbase@npm:^1.0.0": + version: 1.0.0 + resolution: "boolbase@npm:1.0.0" + checksum: 3e25c80ef626c3a3487c73dbfc70ac322ec830666c9ad915d11b701142fab25ec1e63eff2c450c74347acfd2de854ccde865cd79ef4db1683f7c7b046ea43bb0 + languageName: node + linkType: hard + +"boxen@npm:7.0.0": + version: 7.0.0 + resolution: "boxen@npm:7.0.0" + dependencies: + ansi-align: ^3.0.1 + camelcase: ^7.0.0 + chalk: ^5.0.1 + cli-boxes: ^3.0.0 + string-width: ^5.1.2 + type-fest: ^2.13.0 + widest-line: ^4.0.1 + wrap-ansi: ^8.0.1 + checksum: b917cf7a168ef3149635a8c02d5c9717d66182348bd27038d85328ad12655151e3324db0f2815253846c33e5f0ddf28b6cd52d56a12b9f88617b7f8f722b946a + languageName: node + linkType: hard + +"boxen@npm:^5.0.0, boxen@npm:^5.1.2": + version: 5.1.2 + resolution: "boxen@npm:5.1.2" + dependencies: + ansi-align: ^3.0.0 + camelcase: ^6.2.0 + chalk: ^4.1.0 + cli-boxes: ^2.2.1 + string-width: ^4.2.2 + type-fest: ^0.20.2 + widest-line: ^3.1.0 + wrap-ansi: ^7.0.0 + checksum: 82d03e42a72576ff235123f17b7c505372fe05c83f75f61e7d4fa4bcb393897ec95ce766fecb8f26b915f0f7a7227d66e5ec7cef43f5b2bd9d3aeed47ec55877 + languageName: node + linkType: hard + +"boxen@npm:^6.2.1": + version: 6.2.1 + resolution: "boxen@npm:6.2.1" + dependencies: + ansi-align: ^3.0.1 + camelcase: ^6.2.0 + chalk: ^4.1.2 + cli-boxes: ^3.0.0 + string-width: ^5.0.1 + type-fest: ^2.5.0 + widest-line: ^4.0.1 + wrap-ansi: ^8.0.1 + checksum: 2b3226092f1ff8e149c02979098c976552afa15f9e0231c9ed2dfcaaf84604494d16a6f13b647f718439f64d3140a088e822d47c7db00d2266e9ffc8d7321774 + languageName: node + linkType: hard + +"boxen@npm:^7.0.0": + version: 7.1.1 + resolution: "boxen@npm:7.1.1" + dependencies: + ansi-align: ^3.0.1 + camelcase: ^7.0.1 + chalk: ^5.2.0 + cli-boxes: ^3.0.0 + string-width: ^5.1.2 + type-fest: ^2.13.0 + widest-line: ^4.0.1 + wrap-ansi: ^8.1.0 + checksum: ad8833d5f2845b0a728fdf8a0bc1505dff0c518edcb0fd56979a08774b1f26cf48b71e66532179ccdfb9ed95b64aa008689cca26f7776f93f002b8000a683d76 + languageName: node + linkType: hard + +"brace-expansion@npm:^1.1.7": + version: 1.1.11 + resolution: "brace-expansion@npm:1.1.11" + dependencies: + balanced-match: ^1.0.0 + concat-map: 0.0.1 + checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: ^1.0.0 + checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + languageName: node + linkType: hard + +"braces@npm:^3.0.2, braces@npm:~3.0.2": + version: 3.0.2 + resolution: "braces@npm:3.0.2" + dependencies: + fill-range: ^7.0.1 + checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 + languageName: node + linkType: hard + +"brorand@npm:^1.1.0": + version: 1.1.0 + resolution: "brorand@npm:1.1.0" + checksum: 8a05c9f3c4b46572dec6ef71012b1946db6cae8c7bb60ccd4b7dd5a84655db49fe043ecc6272e7ef1f69dc53d6730b9e2a3a03a8310509a3d797a618cbee52be + languageName: node + linkType: hard + +"browser-stdout@npm:1.3.1": + version: 1.3.1 + resolution: "browser-stdout@npm:1.3.1" + checksum: b717b19b25952dd6af483e368f9bcd6b14b87740c3d226c2977a65e84666ffd67000bddea7d911f111a9b6ddc822b234de42d52ab6507bce4119a4cc003ef7b3 + languageName: node + linkType: hard + +"browserify-aes@npm:^1.2.0": + version: 1.2.0 + resolution: "browserify-aes@npm:1.2.0" + dependencies: + buffer-xor: ^1.0.3 + cipher-base: ^1.0.0 + create-hash: ^1.1.0 + evp_bytestokey: ^1.0.3 + inherits: ^2.0.1 + safe-buffer: ^5.0.1 + checksum: 4a17c3eb55a2aa61c934c286f34921933086bf6d67f02d4adb09fcc6f2fc93977b47d9d884c25619144fccd47b3b3a399e1ad8b3ff5a346be47270114bcf7104 + languageName: node + linkType: hard + +"browserify-fs@npm:^1.0.0": + version: 1.0.0 + resolution: "browserify-fs@npm:1.0.0" + dependencies: + level-filesystem: ^1.0.1 + level-js: ^2.1.3 + levelup: ^0.18.2 + checksum: e0c35cf42c839c0a217048b1671d91ee6e53fd05f163db4f809e46c2f6264f784768e7c850abc200b0eaca378d42e00e01876eda21fd84fc0a4280bd6200a9c3 + languageName: node + linkType: hard + +"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.21.9, browserslist@npm:^4.22.2": + version: 4.22.2 + resolution: "browserslist@npm:4.22.2" + dependencies: + caniuse-lite: ^1.0.30001565 + electron-to-chromium: ^1.4.601 + node-releases: ^2.0.14 + update-browserslist-db: ^1.0.13 + bin: + browserslist: cli.js + checksum: 33ddfcd9145220099a7a1ac533cecfe5b7548ffeb29b313e1b57be6459000a1f8fa67e781cf4abee97268ac594d44134fcc4a6b2b4750ceddc9796e3a22076d9 + languageName: node + linkType: hard + +"browserslist@npm:^4.23.0, browserslist@npm:^4.23.1, browserslist@npm:^4.23.3": + version: 4.24.0 + resolution: "browserslist@npm:4.24.0" + dependencies: + caniuse-lite: ^1.0.30001663 + electron-to-chromium: ^1.5.28 + node-releases: ^2.0.18 + update-browserslist-db: ^1.1.0 + bin: + browserslist: cli.js + checksum: de200d3eb8d6ed819dad99719099a28fb6ebeb88016a5ac42fbdc11607e910c236a84ca1b0bbf232477d4b88ab64e8ab6aa67557cdd40a73ca9c2834f92ccce0 + languageName: node + linkType: hard + +"bs58@npm:^4.0.0": + version: 4.0.1 + resolution: "bs58@npm:4.0.1" + dependencies: + base-x: ^3.0.2 + checksum: b3c5365bb9e0c561e1a82f1a2d809a1a692059fae016be233a6127ad2f50a6b986467c3a50669ce4c18929dcccb297c5909314dd347a25a68c21b68eb3e95ac2 + languageName: node + linkType: hard + +"bs58check@npm:^2.1.2": + version: 2.1.2 + resolution: "bs58check@npm:2.1.2" + dependencies: + bs58: ^4.0.0 + create-hash: ^1.1.0 + safe-buffer: ^5.1.2 + checksum: 43bdf08a5dd04581b78f040bc4169480e17008da482ffe2a6507327bbc4fc5c28de0501f7faf22901cfe57fbca79cbb202ca529003fedb4cb8dccd265b38e54d + languageName: node + linkType: hard + +"buffer-crc32@npm:~0.2.3": + version: 0.2.13 + resolution: "buffer-crc32@npm:0.2.13" + checksum: 06252347ae6daca3453b94e4b2f1d3754a3b146a111d81c68924c22d91889a40623264e95e67955b1cb4a68cbedf317abeabb5140a9766ed248973096db5ce1c + languageName: node + linkType: hard + +"buffer-from@npm:^1.0.0": + version: 1.1.2 + resolution: "buffer-from@npm:1.1.2" + checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb + languageName: node + linkType: hard + +"buffer-xor@npm:^1.0.3": + version: 1.0.3 + resolution: "buffer-xor@npm:1.0.3" + checksum: 10c520df29d62fa6e785e2800e586a20fc4f6dfad84bcdbd12e1e8a83856de1cb75c7ebd7abe6d036bbfab738a6cf18a3ae9c8e5a2e2eb3167ca7399ce65373a + languageName: node + linkType: hard + +"buffer@npm:^5.2.1": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: ^1.3.1 + ieee754: ^1.1.13 + checksum: e2cf8429e1c4c7b8cbd30834ac09bd61da46ce35f5c22a78e6c2f04497d6d25541b16881e30a019c6fd3154150650ccee27a308eff3e26229d788bbdeb08ab84 + languageName: node + linkType: hard + +"buffer@npm:^6.0.3": + version: 6.0.3 + resolution: "buffer@npm:6.0.3" + dependencies: + base64-js: ^1.3.1 + ieee754: ^1.2.1 + checksum: 5ad23293d9a731e4318e420025800b42bf0d264004c0286c8cc010af7a270c7a0f6522e84f54b9ad65cbd6db20b8badbfd8d2ebf4f80fa03dab093b89e68c3f9 + languageName: node + linkType: hard + +"builtin-modules@npm:^3.3.0": + version: 3.3.0 + resolution: "builtin-modules@npm:3.3.0" + checksum: db021755d7ed8be048f25668fe2117620861ef6703ea2c65ed2779c9e3636d5c3b82325bd912244293959ff3ae303afa3471f6a15bf5060c103e4cc3a839749d + languageName: node + linkType: hard + +"bundle-name@npm:^4.1.0": + version: 4.1.0 + resolution: "bundle-name@npm:4.1.0" + dependencies: + run-applescript: ^7.0.0 + checksum: 1d966c8d2dbf4d9d394e53b724ac756c2414c45c01340b37743621f59cc565a435024b394ddcb62b9b335d1c9a31f4640eb648c3fec7f97ee74dc0694c9beb6c + languageName: node + linkType: hard + +"bytes@npm:3.0.0": + version: 3.0.0 + resolution: "bytes@npm:3.0.0" + checksum: a2b386dd8188849a5325f58eef69c3b73c51801c08ffc6963eddc9be244089ba32d19347caf6d145c86f315ae1b1fc7061a32b0c1aa6379e6a719090287ed101 + languageName: node + linkType: hard + +"bytes@npm:3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: e4bcd3948d289c5127591fbedf10c0b639ccbf00243504e4e127374a15c3bc8eed0d28d4aaab08ff6f1cf2abc0cce6ba3085ed32f4f90e82a5683ce0014e1b6e + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.1 + resolution: "cacache@npm:18.0.1" + dependencies: + "@npmcli/fs": ^3.1.0 + fs-minipass: ^3.0.0 + glob: ^10.2.2 + lru-cache: ^10.0.1 + minipass: ^7.0.3 + minipass-collect: ^2.0.1 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + p-map: ^4.0.0 + ssri: ^10.0.0 + tar: ^6.1.11 + unique-filename: ^3.0.0 + checksum: 5a0b3b2ea451a0379814dc1d3c81af48c7c6db15cd8f7d72e028501ae0036a599a99bbac9687bfec307afb2760808d1c7708e9477c8c70d2b166e7d80b162a23 + languageName: node + linkType: hard + +"cache-content-type@npm:^1.0.0": + version: 1.0.1 + resolution: "cache-content-type@npm:1.0.1" + dependencies: + mime-types: ^2.1.18 + ylru: ^1.2.0 + checksum: 18db4d59452669ccbfd7146a1510a37eb28e9eccf18ca7a4eb603dff2edc5cccdca7498fc3042a2978f76f11151fba486eb9eb69d9afa3fb124957870aef4fd3 + languageName: node + linkType: hard + +"cacheable-lookup@npm:^7.0.0": + version: 7.0.0 + resolution: "cacheable-lookup@npm:7.0.0" + checksum: 9e2856763fc0a7347ab34d704c010440b819d4bb5e3593b664381b7433e942dd22e67ee5581f12256f908e79b82d30b86ebbacf40a081bfe10ee93fbfbc2d6a9 + languageName: node + linkType: hard + +"cacheable-request@npm:^10.2.8": + version: 10.2.14 + resolution: "cacheable-request@npm:10.2.14" + dependencies: + "@types/http-cache-semantics": ^4.0.2 + get-stream: ^6.0.1 + http-cache-semantics: ^4.1.1 + keyv: ^4.5.3 + mimic-response: ^4.0.0 + normalize-url: ^8.0.0 + responselike: ^3.0.0 + checksum: 56f2b8e1c497c91f8391f0b099d19907a7dde25e71087e622b23e45fc8061736c2a6964ef121b16f377c3c61079cf8dc17320ab54004209d1343e4d26aba7015 + languageName: node + linkType: hard + +"cacheable-request@npm:^6.0.0": + version: 6.1.0 + resolution: "cacheable-request@npm:6.1.0" + dependencies: + clone-response: ^1.0.2 + get-stream: ^5.1.0 + http-cache-semantics: ^4.0.0 + keyv: ^3.0.0 + lowercase-keys: ^2.0.0 + normalize-url: ^4.1.0 + responselike: ^1.0.2 + checksum: b510b237b18d17e89942e9ee2d2a077cb38db03f12167fd100932dfa8fc963424bfae0bfa1598df4ae16c944a5484e43e03df8f32105b04395ee9495e9e4e9f1 + languageName: node + linkType: hard + +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": + version: 1.0.5 + resolution: "call-bind@npm:1.0.5" + dependencies: + function-bind: ^1.1.2 + get-intrinsic: ^1.2.1 + set-function-length: ^1.1.1 + checksum: 449e83ecbd4ba48e7eaac5af26fea3b50f8f6072202c2dd7c5a6e7a6308f2421abe5e13a3bbd55221087f76320c5e09f25a8fdad1bab2b77c68ae74d92234ea5 + languageName: node + linkType: hard + +"callsites@npm:^3.0.0, callsites@npm:^3.1.0": + version: 3.1.0 + resolution: "callsites@npm:3.1.0" + checksum: 072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 + languageName: node + linkType: hard + +"camel-case@npm:^4.1.2": + version: 4.1.2 + resolution: "camel-case@npm:4.1.2" + dependencies: + pascal-case: ^3.1.2 + tslib: ^2.0.3 + checksum: bcbd25cd253b3cbc69be3f535750137dbf2beb70f093bdc575f73f800acc8443d34fd52ab8f0a2413c34f1e8203139ffc88428d8863e4dfe530cfb257a379ad6 + languageName: node + linkType: hard + +"camelcase-css@npm:2.0.1": + version: 2.0.1 + resolution: "camelcase-css@npm:2.0.1" + checksum: 1cec2b3b3dcb5026688a470b00299a8db7d904c4802845c353dbd12d9d248d3346949a814d83bfd988d4d2e5b9904c07efe76fecd195a1d4f05b543e7c0b56b1 + languageName: node + linkType: hard + +"camelcase@npm:^6.0.0, camelcase@npm:^6.2.0": + version: 6.3.0 + resolution: "camelcase@npm:6.3.0" + checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d + languageName: node + linkType: hard + +"camelcase@npm:^7.0.0, camelcase@npm:^7.0.1": + version: 7.0.1 + resolution: "camelcase@npm:7.0.1" + checksum: 86ab8f3ebf08bcdbe605a211a242f00ed30d8bfb77dab4ebb744dd36efbc84432d1c4adb28975ba87a1b8be40a80fbd1e60e2f06565315918fa7350011a26d3d + languageName: node + linkType: hard + +"caniuse-api@npm:^3.0.0": + version: 3.0.0 + resolution: "caniuse-api@npm:3.0.0" + dependencies: + browserslist: ^4.0.0 + caniuse-lite: ^1.0.0 + lodash.memoize: ^4.1.2 + lodash.uniq: ^4.5.0 + checksum: db2a229383b20d0529b6b589dde99d7b6cb56ba371366f58cbbfa2929c9f42c01f873e2b6ef641d4eda9f0b4118de77dbb2805814670bdad4234bf08e720b0b4 + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001565": + version: 1.0.30001568 + resolution: "caniuse-lite@npm:1.0.30001568" + checksum: 7092aaa246dc8531fbca5b47be91e92065db7e5c04cc9e3d864e848f8f1be769ac6754429e843a5e939f7331a771e8b0a1bc3b13495c66b748c65e2f5bdb1220 + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.30001646, caniuse-lite@npm:^1.0.30001663": + version: 1.0.30001664 + resolution: "caniuse-lite@npm:1.0.30001664" + checksum: cee25b4ea8a84779b7c9a60c1f9e304f6d99b79ef622b25fbc7873b4e55e8722a1091dd6c8b77bd7723e9f26a84b4a820a50a864989dd477e7ee51dc30461dca + languageName: node + linkType: hard + +"ccount@npm:^1.0.0": + version: 1.1.0 + resolution: "ccount@npm:1.1.0" + checksum: b335a79d0aa4308919cf7507babcfa04ac63d389ebed49dbf26990d4607c8a4713cde93cc83e707d84571ddfe1e7615dad248be9bc422ae4c188210f71b08b78 + languageName: node + linkType: hard + +"ccount@npm:^2.0.0": + version: 2.0.1 + resolution: "ccount@npm:2.0.1" + checksum: 48193dada54c9e260e0acf57fc16171a225305548f9ad20d5471e0f7a8c026aedd8747091dccb0d900cde7df4e4ddbd235df0d8de4a64c71b12f0d3303eeafd4 + languageName: node + linkType: hard + +"chai-as-promised@npm:^7.1.1": + version: 7.1.1 + resolution: "chai-as-promised@npm:7.1.1" + dependencies: + check-error: ^1.0.2 + peerDependencies: + chai: ">= 2.1.2 < 5" + checksum: 7262868a5b51a12af4e432838ddf97a893109266a505808e1868ba63a12de7ee1166e9d43b5c501a190c377c1b11ecb9ff8e093c89f097ad96c397e8ec0f8d6a + languageName: node + linkType: hard + +"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 + deep-eql: ^4.1.3 + get-func-name: ^2.0.2 + loupe: ^2.3.6 + pathval: ^1.1.1 + type-detect: ^4.0.8 + checksum: 9ab84f36eb8e0b280c56c6c21ca4da5933132cd8a0c89c384f1497f77953640db0bc151edd47f81748240a9fab57b78f7d925edfeedc8e8fc98016d71f40c36e + languageName: node + linkType: hard + +"chalk-template@npm:0.4.0, chalk-template@npm:^0.4.0": + version: 0.4.0 + resolution: "chalk-template@npm:0.4.0" + dependencies: + chalk: ^4.1.2 + checksum: 6c706802a79a7963cbce18f022b046fe86e438a67843151868852f80ea7346e975a6a9749991601e7e5d3b6a6c4852a04c53dc966a9a3d04031bd0e0ed53c819 + languageName: node + linkType: hard + +"chalk-template@npm:^1.1.0": + version: 1.1.0 + resolution: "chalk-template@npm:1.1.0" + dependencies: + chalk: ^5.2.0 + checksum: 868aae8d4e7556ad2f35de4e04fe65dbe1ea6c5c80ad783f1c156d0a5c33f444c6814f49cbb68fe348c78e99daf2bcf566b47ad7e13603e4691ca78b2f422824 + languageName: node + linkType: hard + +"chalk@npm:5.0.1": + version: 5.0.1 + resolution: "chalk@npm:5.0.1" + checksum: 7b45300372b908f0471fbf7389ce2f5de8d85bb949026fd51a1b95b10d0ed32c7ed5aab36dd5e9d2bf3191867909b4404cef75c5f4d2d1daeeacd301dd280b76 + languageName: node + linkType: hard + +"chalk@npm:^2.4.1, chalk@npm:^2.4.2": + version: 2.4.2 + resolution: "chalk@npm:2.4.2" + dependencies: + ansi-styles: ^3.2.1 + escape-string-regexp: ^1.0.5 + supports-color: ^5.3.0 + checksum: ec3661d38fe77f681200f878edbd9448821924e0f93a9cefc0e26a33b145f1027a2084bf19967160d11e1f03bfe4eaffcabf5493b89098b2782c3fe0b03d80c2 + languageName: node + linkType: hard + +"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc + languageName: node + linkType: hard + +"chalk@npm:^5.0.1, chalk@npm:^5.2.0, chalk@npm:^5.3.0": + version: 5.3.0 + resolution: "chalk@npm:5.3.0" + checksum: 623922e077b7d1e9dedaea6f8b9e9352921f8ae3afe739132e0e00c275971bdd331268183b2628cf4ab1727c45ea1f28d7e24ac23ce1db1eb653c414ca8a5a80 + languageName: node + linkType: hard + +"char-regex@npm:^1.0.2": + version: 1.0.2 + resolution: "char-regex@npm:1.0.2" + checksum: b563e4b6039b15213114626621e7a3d12f31008bdce20f9c741d69987f62aeaace7ec30f6018890ad77b2e9b4d95324c9f5acfca58a9441e3b1dcdd1e2525d17 + languageName: node + linkType: hard + +"character-entities-html4@npm:^2.0.0": + version: 2.1.0 + resolution: "character-entities-html4@npm:2.1.0" + checksum: 7034aa7c7fa90309667f6dd50499c8a760c3d3a6fb159adb4e0bada0107d194551cdbad0714302f62d06ce4ed68565c8c2e15fdef2e8f8764eb63fa92b34b11d + languageName: node + linkType: hard + +"character-entities-legacy@npm:^1.0.0": + version: 1.1.4 + resolution: "character-entities-legacy@npm:1.1.4" + checksum: fe03a82c154414da3a0c8ab3188e4237ec68006cbcd681cf23c7cfb9502a0e76cd30ab69a2e50857ca10d984d57de3b307680fff5328ccd427f400e559c3a811 + languageName: node + linkType: hard + +"character-entities-legacy@npm:^3.0.0": + version: 3.0.0 + resolution: "character-entities-legacy@npm:3.0.0" + checksum: 7582af055cb488b626d364b7d7a4e46b06abd526fb63c0e4eb35bcb9c9799cc4f76b39f34fdccef2d1174ac95e53e9ab355aae83227c1a2505877893fce77731 + languageName: node + linkType: hard + +"character-entities@npm:^1.0.0": + version: 1.2.4 + resolution: "character-entities@npm:1.2.4" + checksum: e1545716571ead57beac008433c1ff69517cd8ca5b336889321c5b8ff4a99c29b65589a701e9c086cda8a5e346a67295e2684f6c7ea96819fe85cbf49bf8686d + languageName: node + linkType: hard + +"character-entities@npm:^2.0.0": + version: 2.0.2 + resolution: "character-entities@npm:2.0.2" + checksum: cf1643814023697f725e47328fcec17923b8f1799102a8a79c1514e894815651794a2bffd84bb1b3a4b124b050154e4529ed6e81f7c8068a734aecf07a6d3def + languageName: node + linkType: hard + +"character-reference-invalid@npm:^1.0.0": + version: 1.1.4 + resolution: "character-reference-invalid@npm:1.1.4" + checksum: 20274574c70e05e2f81135f3b93285536bc8ff70f37f0809b0d17791a832838f1e49938382899ed4cb444e5bbd4314ca1415231344ba29f4222ce2ccf24fea0b + languageName: node + linkType: hard + +"character-reference-invalid@npm:^2.0.0": + version: 2.0.1 + resolution: "character-reference-invalid@npm:2.0.1" + checksum: 98d3b1a52ae510b7329e6ee7f6210df14f1e318c5415975d4c9e7ee0ef4c07875d47c6e74230c64551f12f556b4a8ccc24d9f3691a2aa197019e72a95e9297ee + languageName: node + linkType: hard + +"check-error@npm:^1.0.2, check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" + dependencies: + get-func-name: ^2.0.2 + checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 + languageName: node + linkType: hard + +"cheerio-select@npm:^2.1.0": + version: 2.1.0 + resolution: "cheerio-select@npm:2.1.0" + dependencies: + boolbase: ^1.0.0 + css-select: ^5.1.0 + css-what: ^6.1.0 + domelementtype: ^2.3.0 + domhandler: ^5.0.3 + domutils: ^3.0.1 + checksum: 843d6d479922f28a6c5342c935aff1347491156814de63c585a6eb73baf7bb4185c1b4383a1195dca0f12e3946d737c7763bcef0b9544c515d905c5c44c5308b + languageName: node + linkType: hard + +"cheerio@npm:1.0.0-rc.12, cheerio@npm:^1.0.0-rc.3": + version: 1.0.0-rc.12 + resolution: "cheerio@npm:1.0.0-rc.12" + dependencies: + cheerio-select: ^2.1.0 + dom-serializer: ^2.0.0 + domhandler: ^5.0.3 + domutils: ^3.0.1 + htmlparser2: ^8.0.1 + parse5: ^7.0.0 + parse5-htmlparser2-tree-adapter: ^7.0.0 + checksum: 5d4c1b7a53cf22d3a2eddc0aff70cf23cbb30d01a4c79013e703a012475c02461aa1fcd99127e8d83a02216386ed6942b2c8103845fd0812300dd199e6e7e054 + languageName: node + linkType: hard + +"chokidar@npm:3.5.3, chokidar@npm:^3.4.0, chokidar@npm:^3.4.2, chokidar@npm:^3.4.3, chokidar@npm:^3.5.3": + version: 3.5.3 + resolution: "chokidar@npm:3.5.3" + dependencies: + anymatch: ~3.1.2 + braces: ~3.0.2 + fsevents: ~2.3.2 + glob-parent: ~5.1.2 + is-binary-path: ~2.1.0 + is-glob: ~4.0.1 + normalize-path: ~3.0.0 + readdirp: ~3.6.0 + dependenciesMeta: + fsevents: + optional: true + checksum: b49fcde40176ba007ff361b198a2d35df60d9bb2a5aab228279eb810feae9294a6b4649ab15981304447afe1e6ffbf4788ad5db77235dc770ab777c6e771980c + languageName: node + linkType: hard + +"chokidar@npm:^3.6.0": + version: 3.6.0 + resolution: "chokidar@npm:3.6.0" + dependencies: + anymatch: ~3.1.2 + braces: ~3.0.2 + fsevents: ~2.3.2 + glob-parent: ~5.1.2 + is-binary-path: ~2.1.0 + is-glob: ~4.0.1 + normalize-path: ~3.0.0 + readdirp: ~3.6.0 + dependenciesMeta: + fsevents: + optional: true + checksum: d2f29f499705dcd4f6f3bbed79a9ce2388cf530460122eed3b9c48efeab7a4e28739c6551fd15bec9245c6b9eeca7a32baa64694d64d9b6faeb74ddb8c4a413d + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f + languageName: node + linkType: hard + +"chrome-launcher@npm:^0.15.0": + version: 0.15.2 + resolution: "chrome-launcher@npm:0.15.2" + dependencies: + "@types/node": "*" + escape-string-regexp: ^4.0.0 + is-wsl: ^2.2.0 + lighthouse-logger: ^1.0.0 + bin: + print-chrome-path: bin/print-chrome-path.js + checksum: e1f8131b9f7bd931248ea85f413c6cdb93a0d41440ff5bf0987f36afb081d2b2c7b60ba6062ee7ae2dd9b052143f6b275b38c9eb115d11b49c3ea8829bad7db0 + languageName: node + linkType: hard + +"chrome-trace-event@npm:^1.0.2": + version: 1.0.3 + resolution: "chrome-trace-event@npm:1.0.3" + checksum: cb8b1fc7e881aaef973bd0c4a43cd353c2ad8323fb471a041e64f7c2dd849cde4aad15f8b753331a32dda45c973f032c8a03b8177fc85d60eaa75e91e08bfb97 + languageName: node + linkType: hard + +"chromium-bidi@npm:0.5.12": + version: 0.5.12 + resolution: "chromium-bidi@npm:0.5.12" + dependencies: + mitt: 3.0.1 + urlpattern-polyfill: 10.0.0 + peerDependencies: + devtools-protocol: "*" + checksum: c14aedc9725a813d82ce66423750757383af6d7580b4f22f8756d31a340b8d6d77dd30a4de0e213f2f89e63faf54a333431acc07675791f1c176d2275e499525 + languageName: node + linkType: hard + +"ci-info@npm:^2.0.0": + version: 2.0.0 + resolution: "ci-info@npm:2.0.0" + checksum: 3b374666a85ea3ca43fa49aa3a048d21c9b475c96eb13c133505d2324e7ae5efd6a454f41efe46a152269e9b6a00c9edbe63ec7fa1921957165aae16625acd67 + languageName: node + linkType: hard + +"ci-info@npm:^3.2.0": + version: 3.9.0 + resolution: "ci-info@npm:3.9.0" + checksum: 6b19dc9b2966d1f8c2041a838217299718f15d6c4b63ae36e4674edd2bee48f780e94761286a56aa59eb305a85fbea4ddffb7630ec063e7ec7e7e5ad42549a87 + languageName: node + linkType: hard + +"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": + version: 1.0.4 + resolution: "cipher-base@npm:1.0.4" + dependencies: + inherits: ^2.0.1 + safe-buffer: ^5.0.1 + checksum: 47d3568dbc17431a339bad1fe7dff83ac0891be8206911ace3d3b818fc695f376df809bea406e759cdea07fff4b454fa25f1013e648851bec790c1d75763032e + languageName: node + linkType: hard + +"clean-css@npm:^5.2.2, clean-css@npm:^5.3.0, clean-css@npm:^5.3.2, clean-css@npm:~5.3.2": + version: 5.3.3 + resolution: "clean-css@npm:5.3.3" + dependencies: + source-map: ~0.6.0 + checksum: 941987c14860dd7d346d5cf121a82fd2caf8344160b1565c5387f7ccca4bbcaf885bace961be37c4f4713ce2d8c488dd89483c1add47bb779790edbfdcc79cbc + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 + languageName: node + linkType: hard + +"clear-module@npm:^4.1.2": + version: 4.1.2 + resolution: "clear-module@npm:4.1.2" + dependencies: + parent-module: ^2.0.0 + resolve-from: ^5.0.0 + checksum: 4931f0c461f5d7b9b79f62c2d1bc31c37f7f1d33b4e95eef7080a83955c0374f4c180f5a96cc4d63bbefc64a9aa5d12b155641109e8e489dfa50fd5820e5101f + languageName: node + linkType: hard + +"cli-boxes@npm:^2.2.1": + version: 2.2.1 + resolution: "cli-boxes@npm:2.2.1" + checksum: be79f8ec23a558b49e01311b39a1ea01243ecee30539c880cf14bf518a12e223ef40c57ead0cb44f509bffdffc5c129c746cd50d863ab879385370112af4f585 + languageName: node + linkType: hard + +"cli-boxes@npm:^3.0.0": + version: 3.0.0 + resolution: "cli-boxes@npm:3.0.0" + checksum: 637d84419d293a9eac40a1c8c96a2859e7d98b24a1a317788e13c8f441be052fc899480c6acab3acc82eaf1bccda6b7542d7cdcf5c9c3cc39227175dc098d5b2 + languageName: node + linkType: hard + +"cli-cursor@npm:^3.1.0": + version: 3.1.0 + resolution: "cli-cursor@npm:3.1.0" + dependencies: + restore-cursor: ^3.1.0 + checksum: 2692784c6cd2fd85cfdbd11f53aea73a463a6d64a77c3e098b2b4697a20443f430c220629e1ca3b195ea5ac4a97a74c2ee411f3807abf6df2b66211fec0c0a29 + languageName: node + linkType: hard + +"cli-table3@npm:^0.6.2, cli-table3@npm:^0.6.3": + version: 0.6.3 + resolution: "cli-table3@npm:0.6.3" + dependencies: + "@colors/colors": 1.5.0 + string-width: ^4.2.0 + dependenciesMeta: + "@colors/colors": + optional: true + checksum: 09897f68467973f827c04e7eaadf13b55f8aec49ecd6647cc276386ea660059322e2dd8020a8b6b84d422dbdd619597046fa89cbbbdc95b2cea149a2df7c096c + languageName: node + linkType: hard + +"clipboardy@npm:3.0.0": + version: 3.0.0 + resolution: "clipboardy@npm:3.0.0" + dependencies: + arch: ^2.2.0 + execa: ^5.1.1 + is-wsl: ^2.2.0 + checksum: 2c292acb59705494cbe07d7df7c8becff4f01651514d32ebd80f4aec2d20946d8f3824aac67ecdf2d09ef21fdf0eb24b6a7f033c137ccdceedc4661c54455c94 + languageName: node + linkType: hard + +"cliui@npm:^7.0.2": + version: 7.0.4 + resolution: "cliui@npm:7.0.4" + dependencies: + string-width: ^4.2.0 + strip-ansi: ^6.0.0 + wrap-ansi: ^7.0.0 + checksum: ce2e8f578a4813806788ac399b9e866297740eecd4ad1823c27fd344d78b22c5f8597d548adbcc46f0573e43e21e751f39446c5a5e804a12aace402b7a315d7f + languageName: node + linkType: hard + +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: ^4.2.0 + strip-ansi: ^6.0.1 + wrap-ansi: ^7.0.0 + checksum: 79648b3b0045f2e285b76fb2e24e207c6db44323581e421c3acbd0e86454cba1b37aea976ab50195a49e7384b871e6dfb2247ad7dec53c02454ac6497394cb56 + languageName: node + linkType: hard + +"clone-deep@npm:^4.0.1": + version: 4.0.1 + resolution: "clone-deep@npm:4.0.1" + dependencies: + is-plain-object: ^2.0.4 + kind-of: ^6.0.2 + shallow-clone: ^3.0.0 + checksum: 770f912fe4e6f21873c8e8fbb1e99134db3b93da32df271d00589ea4a29dbe83a9808a322c93f3bcaf8584b8b4fa6fc269fc8032efbaa6728e0c9886c74467d2 + languageName: node + linkType: hard + +"clone-response@npm:^1.0.2": + version: 1.0.3 + resolution: "clone-response@npm:1.0.3" + dependencies: + mimic-response: ^1.0.0 + checksum: 4e671cac39b11c60aa8ba0a450657194a5d6504df51bca3fac5b3bd0145c4f8e8464898f87c8406b83232e3bc5cca555f51c1f9c8ac023969ebfbf7f6bdabb2e + languageName: node + linkType: hard + +"clone@npm:^2.1.2": + version: 2.1.2 + resolution: "clone@npm:2.1.2" + checksum: aaf106e9bc025b21333e2f4c12da539b568db4925c0501a1bf4070836c9e848c892fa22c35548ce0d1132b08bbbfa17a00144fe58fccdab6fa900fec4250f67d + languageName: node + linkType: hard + +"clone@npm:~0.1.9": + version: 0.1.19 + resolution: "clone@npm:0.1.19" + checksum: 5e710e16da67abe30c0664c8fd69c280635be59a4fae0a5fe58ed324e701e99348b48ce67288716fa223edd42ba574e58a3783cb2fcfa381b8b49ce7e56ac3f4 + languageName: node + linkType: hard + +"clsx@npm:^1.1.1, clsx@npm:^1.2.1": + version: 1.2.1 + resolution: "clsx@npm:1.2.1" + checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12 + languageName: node + linkType: hard + +"clsx@npm:^2.0.0": + version: 2.0.0 + resolution: "clsx@npm:2.0.0" + checksum: a2cfb2351b254611acf92faa0daf15220f4cd648bdf96ce369d729813b85336993871a4bf6978ddea2b81b5a130478339c20d9d0b5c6fc287e5147f0c059276e + languageName: node + linkType: hard + +"co-body@npm:^6.1.0": + version: 6.1.0 + resolution: "co-body@npm:6.1.0" + dependencies: + inflation: ^2.0.0 + qs: ^6.5.2 + raw-body: ^2.3.3 + type-is: ^1.6.16 + checksum: d0a78831a6651f2085fce16b0ecdc49f45fb5baf4f94148c2f499e7ec89d188205362548b9c500eae15a819360cfda208079e68a72c204cf66ca3ffa2fc0f57e + languageName: node + linkType: hard + +"co@npm:^4.6.0": + version: 4.6.0 + resolution: "co@npm:4.6.0" + checksum: 5210d9223010eb95b29df06a91116f2cf7c8e0748a9013ed853b53f362ea0e822f1e5bb054fb3cefc645239a4cf966af1f6133a3b43f40d591f3b68ed6cf0510 + languageName: node + linkType: hard + +"collapse-white-space@npm:^1.0.2": + version: 1.0.6 + resolution: "collapse-white-space@npm:1.0.6" + checksum: 9673fb797952c5c888341435596c69388b22cd5560c8cd3f40edb72734a9c820f56a7c9525166bcb7068b5d5805372e6fd0c4b9f2869782ad070cb5d3faf26e7 + languageName: node + linkType: hard + +"collapse-white-space@npm:^2.0.0": + version: 2.1.0 + resolution: "collapse-white-space@npm:2.1.0" + checksum: c8978b1f4e7d68bf846cfdba6c6689ce8910511df7d331eb6e6757e51ceffb52768d59a28db26186c91dcf9594955b59be9f8ccd473c485790f5d8b90dc6726f + languageName: node + linkType: hard + +"color-convert@npm:^1.9.0": + version: 1.9.3 + resolution: "color-convert@npm:1.9.3" + dependencies: + color-name: 1.1.3 + checksum: fd7a64a17cde98fb923b1dd05c5f2e6f7aefda1b60d67e8d449f9328b4e53b228a428fd38bfeaeb2db2ff6b6503a776a996150b80cdf224062af08a5c8a3a203 + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: ~1.1.4 + checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 + languageName: node + linkType: hard + +"color-name@npm:1.1.3": + version: 1.1.3 + resolution: "color-name@npm:1.1.3" + checksum: 09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 + languageName: node + linkType: hard + +"colord@npm:^2.9.1, colord@npm:^2.9.3": + version: 2.9.3 + resolution: "colord@npm:2.9.3" + checksum: 95d909bfbcfd8d5605cbb5af56f2d1ce2b323990258fd7c0d2eb0e6d3bb177254d7fb8213758db56bb4ede708964f78c6b992b326615f81a18a6aaf11d64c650 + languageName: node + linkType: hard + +"colorette@npm:^2.0.10, colorette@npm:^2.0.14": + version: 2.0.20 + resolution: "colorette@npm:2.0.20" + checksum: 0c016fea2b91b733eb9f4bcdb580018f52c0bc0979443dad930e5037a968237ac53d9beb98e218d2e9235834f8eebce7f8e080422d6194e957454255bde71d3d + languageName: node + linkType: hard + +"combine-promises@npm:^1.1.0": + version: 1.2.0 + resolution: "combine-promises@npm:1.2.0" + checksum: ddce91436e24da03d5dc360c59cd55abfc9da5e949a26255aa42761925c574797c43138f0aabfc364e184e738e5e218a94ac6e88ebc459045bcf048ac7fe5f07 + languageName: node + linkType: hard + +"combined-stream@npm:^1.0.8": + version: 1.0.8 + resolution: "combined-stream@npm:1.0.8" + dependencies: + delayed-stream: ~1.0.0 + checksum: 49fa4aeb4916567e33ea81d088f6584749fc90c7abec76fd516bf1c5aa5c79f3584b5ba3de6b86d26ddd64bae5329c4c7479343250cfe71c75bb366eae53bb7c + languageName: node + linkType: hard + +"comlink@npm:^4.4.1": + version: 4.4.1 + resolution: "comlink@npm:4.4.1" + checksum: 16d58a8f590087fc45432e31d6c138308dfd4b75b89aec0b7f7bb97ad33d810381bd2b1e608a1fb2cf05979af9cbfcdcaf1715996d5fcf77aeb013b6da3260af + languageName: node + linkType: hard + +"comma-separated-tokens@npm:^1.0.0": + version: 1.0.8 + resolution: "comma-separated-tokens@npm:1.0.8" + checksum: 0adcb07174fa4d08cf0f5c8e3aec40a36b5ff0c2c720e5e23f50fe02e6789d1d00a67036c80e0c1e1539f41d3e7f0101b074039dd833b4e4a59031b659d6ca0d + languageName: node + linkType: hard + +"comma-separated-tokens@npm:^2.0.0": + version: 2.0.3 + resolution: "comma-separated-tokens@npm:2.0.3" + checksum: e3bf9e0332a5c45f49b90e79bcdb4a7a85f28d6a6f0876a94f1bb9b2bfbdbbb9292aac50e1e742d8c0db1e62a0229a106f57917e2d067fca951d81737651700d + languageName: node + linkType: hard + +"command-exists@npm:^1.2.7, command-exists@npm:^1.2.8": + version: 1.2.9 + resolution: "command-exists@npm:1.2.9" + checksum: 729ae3d88a2058c93c58840f30341b7f82688a573019535d198b57a4d8cb0135ced0ad7f52b591e5b28a90feb2c675080ce916e56254a0f7c15cb2395277cac3 + languageName: node + linkType: hard + +"command-line-args@npm:^5.1.1, command-line-args@npm:^5.2.1": + version: 5.2.1 + resolution: "command-line-args@npm:5.2.1" + dependencies: + array-back: ^3.1.0 + find-replace: ^3.0.0 + lodash.camelcase: ^4.3.0 + typical: ^4.0.0 + checksum: e759519087be3cf2e86af8b9a97d3058b4910cd11ee852495be881a067b72891f6a32718fb685ee6d41531ab76b2b7bfb6602f79f882cd4b7587ff1e827982c7 + languageName: node + linkType: hard + +"command-line-usage@npm:^6.1.0": + version: 6.1.3 + resolution: "command-line-usage@npm:6.1.3" + dependencies: + array-back: ^4.0.2 + chalk: ^2.4.2 + table-layout: ^1.0.2 + typical: ^5.2.0 + checksum: 8261d4e5536eb0bcddee0ec5e89c05bb2abd18e5760785c8078ede5020bc1c612cbe28eb6586f5ed4a3660689748e5aaad4a72f21566f4ef39393694e2fa1a0b + languageName: node + linkType: hard + +"command-line-usage@npm:^7.0.0, command-line-usage@npm:^7.0.1": + version: 7.0.1 + resolution: "command-line-usage@npm:7.0.1" + dependencies: + array-back: ^6.2.2 + chalk-template: ^0.4.0 + table-layout: ^3.0.0 + typical: ^7.1.1 + checksum: ac78ad6b83b9622bb111ae8e82205bde1d2da74df237fdd0bd7d98eda3592c8933ec600818b0b028b2313ddca638b1b60f0780dd9457ad4a0384b17156641f79 + languageName: node + linkType: hard + +"commander@npm:^10.0.0, commander@npm:^10.0.1": + version: 10.0.1 + resolution: "commander@npm:10.0.1" + checksum: 436901d64a818295803c1996cd856621a74f30b9f9e28a588e726b2b1670665bccd7c1a77007ebf328729f0139838a88a19265858a0fa7a8728c4656796db948 + languageName: node + linkType: hard + +"commander@npm:^11.1.0": + version: 11.1.0 + resolution: "commander@npm:11.1.0" + checksum: fd1a8557c6b5b622c89ecdfde703242ab7db3b628ea5d1755784c79b8e7cb0d74d65b4a262289b533359cd58e1bfc0bf50245dfbcd2954682a6f367c828b79ef + languageName: node + linkType: hard + +"commander@npm:^2.20.0": + version: 2.20.3 + resolution: "commander@npm:2.20.3" + checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e + languageName: node + linkType: hard + +"commander@npm:^5.1.0": + version: 5.1.0 + resolution: "commander@npm:5.1.0" + checksum: 0b7fec1712fbcc6230fcb161d8d73b4730fa91a21dc089515489402ad78810547683f058e2a9835929c212fead1d6a6ade70db28bbb03edbc2829a9ab7d69447 + languageName: node + linkType: hard + +"commander@npm:^7.2.0": + version: 7.2.0 + resolution: "commander@npm:7.2.0" + checksum: 53501cbeee61d5157546c0bef0fedb6cdfc763a882136284bed9a07225f09a14b82d2a84e7637edfd1a679fb35ed9502fd58ef1d091e6287f60d790147f68ddc + languageName: node + linkType: hard + +"commander@npm:^8.1.0, commander@npm:^8.3.0": + version: 8.3.0 + resolution: "commander@npm:8.3.0" + checksum: 0f82321821fc27b83bd409510bb9deeebcfa799ff0bf5d102128b500b7af22872c0c92cb6a0ebc5a4cf19c6b550fba9cedfa7329d18c6442a625f851377bacf0 + languageName: node + linkType: hard + +"comment-json@npm:^4.2.3": + version: 4.2.3 + resolution: "comment-json@npm:4.2.3" + dependencies: + array-timsort: ^1.0.3 + core-util-is: ^1.0.3 + esprima: ^4.0.1 + has-own-prop: ^2.0.0 + repeat-string: ^1.6.1 + checksum: 7f8d26266b0d49de9661f6365cbcc373fee4f4d0f422a203dfb17ad8f3d84c5be5ded444874935a197cd03cff297c53fe48910256cb4171cb2e52a3e6b9d317c + languageName: node + linkType: hard + +"common-path-prefix@npm:^3.0.0": + version: 3.0.0 + resolution: "common-path-prefix@npm:3.0.0" + checksum: fdb3c4f54e51e70d417ccd950c07f757582de800c0678ca388aedefefc84982039f346f9fd9a1252d08d2da9e9ef4019f580a1d1d3a10da031e4bb3c924c5818 + languageName: node + linkType: hard + +"commondir@npm:^1.0.1": + version: 1.0.1 + resolution: "commondir@npm:1.0.1" + checksum: 59715f2fc456a73f68826285718503340b9f0dd89bfffc42749906c5cf3d4277ef11ef1cca0350d0e79204f00f1f6d83851ececc9095dc88512a697ac0b9bdcb + languageName: node + linkType: hard + +"compressible@npm:~2.0.16": + version: 2.0.18 + resolution: "compressible@npm:2.0.18" + dependencies: + mime-db: ">= 1.43.0 < 2" + checksum: 58321a85b375d39230405654721353f709d0c1442129e9a17081771b816302a012471a9b8f4864c7dbe02eef7f2aaac3c614795197092262e94b409c9be108f0 + languageName: node + linkType: hard + +"compression@npm:1.7.4, compression@npm:^1.7.4": + version: 1.7.4 + resolution: "compression@npm:1.7.4" + dependencies: + accepts: ~1.3.5 + bytes: 3.0.0 + compressible: ~2.0.16 + debug: 2.6.9 + on-headers: ~1.0.2 + safe-buffer: 5.1.2 + vary: ~1.1.2 + checksum: 35c0f2eb1f28418978615dc1bc02075b34b1568f7f56c62d60f4214d4b7cc00d0f6d282b5f8a954f59872396bd770b6b15ffd8aa94c67d4bce9b8887b906999b + languageName: node + linkType: hard + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af + languageName: node + linkType: hard + +"concat-stream@npm:^1.4.4": + version: 1.6.2 + resolution: "concat-stream@npm:1.6.2" + dependencies: + buffer-from: ^1.0.0 + inherits: ^2.0.3 + readable-stream: ^2.2.2 + typedarray: ^0.0.6 + checksum: 1ef77032cb4459dcd5187bd710d6fc962b067b64ec6a505810de3d2b8cc0605638551b42f8ec91edf6fcd26141b32ef19ad749239b58fae3aba99187adc32285 + languageName: node + linkType: hard + +"config-chain@npm:^1.1.11": + version: 1.1.13 + resolution: "config-chain@npm:1.1.13" + dependencies: + ini: ^1.3.4 + proto-list: ~1.2.1 + checksum: 828137a28e7c2fc4b7fb229bd0cd6c1397bcf83434de54347e608154008f411749041ee392cbe42fab6307e02de4c12480260bf769b7d44b778fdea3839eafab + languageName: node + linkType: hard + +"configstore@npm:^5.0.1": + version: 5.0.1 + resolution: "configstore@npm:5.0.1" + dependencies: + dot-prop: ^5.2.0 + graceful-fs: ^4.1.2 + make-dir: ^3.0.0 + unique-string: ^2.0.0 + write-file-atomic: ^3.0.0 + xdg-basedir: ^4.0.0 + checksum: 60ef65d493b63f96e14b11ba7ec072fdbf3d40110a94fb7199d1c287761bdea5c5244e76b2596325f30c1b652213aa75de96ea20afd4a5f82065e61ea090988e + languageName: node + linkType: hard + +"configstore@npm:^6.0.0": + version: 6.0.0 + resolution: "configstore@npm:6.0.0" + dependencies: + dot-prop: ^6.0.1 + graceful-fs: ^4.2.6 + unique-string: ^3.0.0 + write-file-atomic: ^3.0.3 + xdg-basedir: ^5.0.1 + checksum: 81995351c10bc04c58507f17748477aeac6f47465109d20e3534cebc881d22e927cfd29e73dd852c46c55f62c2b7be4cd1fe6eb3a93ba51f7f9813c218f9bae0 + languageName: node + linkType: hard + +"connect-history-api-fallback@npm:^2.0.0": + version: 2.0.0 + resolution: "connect-history-api-fallback@npm:2.0.0" + checksum: dc5368690f4a5c413889792f8df70d5941ca9da44523cde3f87af0745faee5ee16afb8195434550f0504726642734f2683d6c07f8b460f828a12c45fbd4c9a68 + languageName: node + linkType: hard + +"consola@npm:^2.15.3": + version: 2.15.3 + resolution: "consola@npm:2.15.3" + checksum: 8ef7a09b703ec67ac5c389a372a33b6dc97eda6c9876443a60d76a3076eea0259e7f67a4e54fd5a52f97df73690822d090cf8b7e102b5761348afef7c6d03e28 + languageName: node + linkType: hard + +"content-disposition@npm:0.5.2": + version: 0.5.2 + resolution: "content-disposition@npm:0.5.2" + checksum: 298d7da63255a38f7858ee19c7b6aae32b167e911293174b4c1349955e97e78e1d0b0d06c10e229405987275b417cf36ff65cbd4821a98bc9df4e41e9372cde7 + languageName: node + linkType: hard + +"content-disposition@npm:0.5.4, content-disposition@npm:~0.5.2": + version: 0.5.4 + resolution: "content-disposition@npm:0.5.4" + dependencies: + safe-buffer: 5.2.1 + checksum: afb9d545e296a5171d7574fcad634b2fdf698875f4006a9dd04a3e1333880c5c0c98d47b560d01216fb6505a54a2ba6a843ee3a02ec86d7e911e8315255f56c3 + languageName: node + linkType: hard + +"content-type@npm:^1.0.4, content-type@npm:~1.0.4": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 + languageName: node + linkType: hard + +"convert-source-map@npm:^1.7.0": + version: 1.9.0 + resolution: "convert-source-map@npm:1.9.0" + checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 + languageName: node + linkType: hard + +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 63ae9933be5a2b8d4509daca5124e20c14d023c820258e484e32dc324d34c2754e71297c94a05784064ad27615037ef677e3f0c00469fb55f409d2bb21261035 + languageName: node + linkType: hard + +"cookie-signature@npm:1.0.6": + version: 1.0.6 + resolution: "cookie-signature@npm:1.0.6" + checksum: f4e1b0a98a27a0e6e66fd7ea4e4e9d8e038f624058371bf4499cfcd8f3980be9a121486995202ba3fca74fbed93a407d6d54d43a43f96fd28d0bd7a06761591a + languageName: node + linkType: hard + +"cookie@npm:0.5.0": + version: 0.5.0 + resolution: "cookie@npm:0.5.0" + checksum: 1f4bd2ca5765f8c9689a7e8954183f5332139eb72b6ff783d8947032ec1fdf43109852c178e21a953a30c0dd42257828185be01b49d1eb1a67fd054ca588a180 + languageName: node + linkType: hard + +"cookie@npm:^0.4.1": + version: 0.4.2 + resolution: "cookie@npm:0.4.2" + checksum: a00833c998bedf8e787b4c342defe5fa419abd96b32f4464f718b91022586b8f1bafbddd499288e75c037642493c83083da426c6a9080d309e3bd90fd11baa9b + languageName: node + linkType: hard + +"cookies@npm:~0.8.0": + version: 0.8.0 + resolution: "cookies@npm:0.8.0" + dependencies: + depd: ~2.0.0 + keygrip: ~1.1.0 + checksum: 806055a44f128705265b1bc6a853058da18bf80dea3654ad99be20985b1fa1b14f86c1eef73644aab8071241f8a78acd57202b54c4c5c70769fc694fbb9c4edc + languageName: node + linkType: hard + +"copy-text-to-clipboard@npm:^3.2.0": + version: 3.2.0 + resolution: "copy-text-to-clipboard@npm:3.2.0" + checksum: df7115c197a166d51f59e4e20ab2a68a855ae8746d25ff149b5465c694d9a405c7e6684b73a9f87ba8d653070164e229c15dfdb9fd77c30be1ff0da569661060 + languageName: node + linkType: hard + +"copy-webpack-plugin@npm:^11.0.0": + version: 11.0.0 + resolution: "copy-webpack-plugin@npm:11.0.0" + dependencies: + fast-glob: ^3.2.11 + glob-parent: ^6.0.1 + globby: ^13.1.1 + normalize-path: ^3.0.0 + schema-utils: ^4.0.0 + serialize-javascript: ^6.0.0 + peerDependencies: + webpack: ^5.1.0 + checksum: df4f8743f003a29ee7dd3d9b1789998a3a99051c92afb2ba2203d3dacfa696f4e757b275560fafb8f206e520a0aa78af34b990324a0e36c2326cefdeef3ca82e + languageName: node + linkType: hard + +"copy-webpack-plugin@npm:^12.0.2": + version: 12.0.2 + resolution: "copy-webpack-plugin@npm:12.0.2" + dependencies: + fast-glob: ^3.3.2 + glob-parent: ^6.0.1 + globby: ^14.0.0 + normalize-path: ^3.0.0 + schema-utils: ^4.2.0 + serialize-javascript: ^6.0.2 + peerDependencies: + webpack: ^5.1.0 + checksum: 98127735336c6db5924688486d3a1854a41835963d0c0b81695b2e3d58c6675164be7d23dee7090b84a56d3c9923175d3d0863ac1942bcc3317d2efc1962b927 + languageName: node + linkType: hard + +"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": + version: 3.34.0 + resolution: "core-js-compat@npm:3.34.0" + dependencies: + browserslist: ^4.22.2 + checksum: 6281f7f57a72f254c06611ec088445e11cf84e0b4edfb5f43dece1a1ff8b0ed0e81ed0bc291024761cd90c39d0f007d8bc46548265139808081d311c7cbc9c81 + languageName: node + linkType: hard + +"core-js-compat@npm:^3.37.1, core-js-compat@npm:^3.38.0": + version: 3.38.1 + resolution: "core-js-compat@npm:3.38.1" + dependencies: + browserslist: ^4.23.3 + checksum: a0a5673bcd59f588f0cd0b59cdacd4712b82909738a87406d334dd412eb3d273ae72b275bdd8e8fef63fca9ef12b42ed651be139c7c44c8a1acb423c8906992e + languageName: node + linkType: hard + +"core-js-pure@npm:^3.30.2": + version: 3.34.0 + resolution: "core-js-pure@npm:3.34.0" + checksum: 4c44ac4beff42e07f41eef3c9ecefc8ee3f9e91e1b9f278bf8520cc1fb37afb663cff77c182541dc42d58737f93ab0f30a33a5fe661fb161fdd8aa7fe78a5edf + languageName: node + linkType: hard + +"core-js@npm:^3.23.3, core-js@npm:^3.31.1": + version: 3.34.0 + resolution: "core-js@npm:3.34.0" + checksum: 26b0d103716b33fc660ee8737da7bc9475fbc655f93bbf1360ab692966449d18f2fc393805095937283db9f919ca2aa5c88d86d16f2846217983ad7da707e31e + languageName: node + linkType: hard + +"core-util-is@npm:^1.0.3, core-util-is@npm:~1.0.0": + version: 1.0.3 + resolution: "core-util-is@npm:1.0.3" + checksum: 9de8597363a8e9b9952491ebe18167e3b36e7707569eed0ebf14f8bba773611376466ae34575bca8cfe3c767890c859c74056084738f09d4e4a6f902b2ad7d99 + languageName: node + linkType: hard + +"cosmiconfig@npm:^6.0.0": + version: 6.0.0 + resolution: "cosmiconfig@npm:6.0.0" + dependencies: + "@types/parse-json": ^4.0.0 + import-fresh: ^3.1.0 + parse-json: ^5.0.0 + path-type: ^4.0.0 + yaml: ^1.7.2 + checksum: 8eed7c854b91643ecb820767d0deb038b50780ecc3d53b0b19e03ed8aabed4ae77271198d1ae3d49c3b110867edf679f5faad924820a8d1774144a87cb6f98fc + languageName: node + linkType: hard + +"cosmiconfig@npm:^7.0.1": + version: 7.1.0 + resolution: "cosmiconfig@npm:7.1.0" + dependencies: + "@types/parse-json": ^4.0.0 + import-fresh: ^3.2.1 + parse-json: ^5.0.0 + path-type: ^4.0.0 + yaml: ^1.10.0 + checksum: c53bf7befc1591b2651a22414a5e786cd5f2eeaa87f3678a3d49d6069835a9d8d1aef223728e98aa8fec9a95bf831120d245096db12abe019fecb51f5696c96f + languageName: node + linkType: hard + +"cosmiconfig@npm:^8.1.3, cosmiconfig@npm:^8.2.0": + version: 8.3.6 + resolution: "cosmiconfig@npm:8.3.6" + dependencies: + import-fresh: ^3.3.0 + js-yaml: ^4.1.0 + parse-json: ^5.2.0 + path-type: ^4.0.0 + peerDependencies: + typescript: ">=4.9.5" + peerDependenciesMeta: + typescript: + optional: true + checksum: dc339ebea427898c9e03bf01b56ba7afbac07fc7d2a2d5a15d6e9c14de98275a9565da949375aee1809591c152c0a3877bb86dbeaf74d5bd5aaa79955ad9e7a0 + languageName: node + linkType: hard + +"create-hash@npm:^1.1.0, create-hash@npm:^1.1.2, create-hash@npm:^1.2.0": + version: 1.2.0 + resolution: "create-hash@npm:1.2.0" + dependencies: + cipher-base: ^1.0.1 + inherits: ^2.0.1 + md5.js: ^1.3.4 + ripemd160: ^2.0.1 + sha.js: ^2.4.0 + checksum: 02a6ae3bb9cd4afee3fabd846c1d8426a0e6b495560a977ba46120c473cb283be6aa1cace76b5f927cf4e499c6146fb798253e48e83d522feba807d6b722eaa9 + languageName: node + linkType: hard + +"create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": + version: 1.1.7 + resolution: "create-hmac@npm:1.1.7" + dependencies: + cipher-base: ^1.0.3 + create-hash: ^1.1.0 + inherits: ^2.0.1 + ripemd160: ^2.0.0 + safe-buffer: ^5.0.1 + sha.js: ^2.4.8 + checksum: ba12bb2257b585a0396108c72830e85f882ab659c3320c83584b1037f8ab72415095167ced80dc4ce8e446a8ecc4b2acf36d87befe0707d73b26cf9dc77440ed + languageName: node + linkType: hard + +"create-require@npm:^1.1.0": + version: 1.1.1 + resolution: "create-require@npm:1.1.1" + checksum: a9a1503d4390d8b59ad86f4607de7870b39cad43d929813599a23714831e81c520bddf61bcdd1f8e30f05fd3a2b71ae8538e946eb2786dc65c2bbc520f692eff + languageName: node + linkType: hard + +"cross-fetch@npm:4.0.0": + version: 4.0.0 + resolution: "cross-fetch@npm:4.0.0" + dependencies: + node-fetch: ^2.6.12 + checksum: ecca4f37ffa0e8283e7a8a590926b66713a7ef7892757aa36c2d20ffa27b0ac5c60dcf453119c809abe5923fc0bae3702a4d896bfb406ef1077b0d0018213e24 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: ^3.1.0 + shebang-command: ^2.0.0 + which: ^2.0.1 + checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 + languageName: node + linkType: hard + +"crypto-random-string@npm:^2.0.0": + version: 2.0.0 + resolution: "crypto-random-string@npm:2.0.0" + checksum: 0283879f55e7c16fdceacc181f87a0a65c53bc16ffe1d58b9d19a6277adcd71900d02bb2c4843dd55e78c51e30e89b0fec618a7f170ebcc95b33182c28f05fd6 + languageName: node + linkType: hard + +"crypto-random-string@npm:^4.0.0": + version: 4.0.0 + resolution: "crypto-random-string@npm:4.0.0" + dependencies: + type-fest: ^1.0.1 + checksum: 91f148f27bcc8582798f0fb3e75a09d9174557f39c3c40a89dd1bd70fb5a14a02548245aa26fa7d663c426ac5026f4729841231c84f9e30e8c8ece5e38656741 + languageName: node + linkType: hard + +"cspell-config-lib@npm:8.3.2": + version: 8.3.2 + resolution: "cspell-config-lib@npm:8.3.2" + dependencies: + "@cspell/cspell-types": 8.3.2 + comment-json: ^4.2.3 + yaml: ^2.3.4 + checksum: 7d5563c2a49f13e9e2b965258f8d5539e282c75234f4375831db3f7ee3c209aa246f07f8bbbc7e7195c248edfdc3a58cb590c5119ad866446ee47df07a593481 + languageName: node + linkType: hard + +"cspell-dictionary@npm:8.3.2": + version: 8.3.2 + resolution: "cspell-dictionary@npm:8.3.2" + dependencies: + "@cspell/cspell-pipe": 8.3.2 + "@cspell/cspell-types": 8.3.2 + cspell-trie-lib: 8.3.2 + fast-equals: ^5.0.1 + gensequence: ^6.0.0 + checksum: 374e8cc94b7d46230b8a3ddb066c14bee746963c01b13a60bf43cfb2e6da1a32dcf963c573016aee3fdf8ffbda6253850679d4c93257de2bf4ec45d4cbaf5888 + languageName: node + linkType: hard + +"cspell-gitignore@npm:8.3.2": + version: 8.3.2 + resolution: "cspell-gitignore@npm:8.3.2" + dependencies: + cspell-glob: 8.3.2 + find-up-simple: ^1.0.0 + bin: + cspell-gitignore: bin.mjs + checksum: 0ae847391993078bca601214812aa9476311d501fcc3a20ceb6e4a22825335188354f71328b0ebc45d6ed35756c6d29062cb4e4b2c26a28a9fb57d3573113b01 + languageName: node + linkType: hard + +"cspell-glob@npm:8.3.2": + version: 8.3.2 + resolution: "cspell-glob@npm:8.3.2" + dependencies: + micromatch: ^4.0.5 + checksum: c1abb55fdfde46014963ccd73451218bec7cd9bc0f3cb9308efa0cf066c7783eb69749400aa0d0c1507fbac3fe598ccc26eb5932985db01264ca933f7564a5b2 + languageName: node + linkType: hard + +"cspell-grammar@npm:8.3.2": + version: 8.3.2 + resolution: "cspell-grammar@npm:8.3.2" + dependencies: + "@cspell/cspell-pipe": 8.3.2 + "@cspell/cspell-types": 8.3.2 + bin: + cspell-grammar: bin.mjs + checksum: 3f48e267f6c26c98f7f24159460bad1b341e0560f00a2e62761ad49ba3fcc8e953af3e4a712e598b2525242cb3dddfb339d85e9917fd72aca33ab292cea71bc9 + languageName: node + linkType: hard + +"cspell-io@npm:8.3.2": + version: 8.3.2 + resolution: "cspell-io@npm:8.3.2" + dependencies: + "@cspell/cspell-service-bus": 8.3.2 + checksum: 609f544d6c23dd471548cbc531ad5d704db4ffaa0513611cdc5f731e9f4de24057dcbc4c1d11e94df3725129549fe2629c9e73750f7de4d3a61eae2cbef13ff1 + languageName: node + linkType: hard + +"cspell-lib@npm:8.3.2": + version: 8.3.2 + resolution: "cspell-lib@npm:8.3.2" + dependencies: + "@cspell/cspell-bundled-dicts": 8.3.2 + "@cspell/cspell-pipe": 8.3.2 + "@cspell/cspell-resolver": 8.3.2 + "@cspell/cspell-types": 8.3.2 + "@cspell/dynamic-import": 8.3.2 + "@cspell/strong-weak-map": 8.3.2 + clear-module: ^4.1.2 + comment-json: ^4.2.3 + configstore: ^6.0.0 + cspell-config-lib: 8.3.2 + cspell-dictionary: 8.3.2 + cspell-glob: 8.3.2 + cspell-grammar: 8.3.2 + cspell-io: 8.3.2 + cspell-trie-lib: 8.3.2 + fast-equals: ^5.0.1 + gensequence: ^6.0.0 + import-fresh: ^3.3.0 + resolve-from: ^5.0.0 + vscode-languageserver-textdocument: ^1.0.11 + vscode-uri: ^3.0.8 + checksum: 398f8b799aa4b7e60b9a0b2e751fbd0d3d81f8ccdc0b331668568ab5f4cced0e64ddc8325a7901ae950fd3838f8fb37bb4dd8f73938fb78b50bdd5f2f5668375 + languageName: node + linkType: hard + +"cspell-trie-lib@npm:8.3.2": + version: 8.3.2 + resolution: "cspell-trie-lib@npm:8.3.2" + dependencies: + "@cspell/cspell-pipe": 8.3.2 + "@cspell/cspell-types": 8.3.2 + gensequence: ^6.0.0 + checksum: 43d3bcf4c1bf1d8fce9601beec52a4f5bd2e27ccd1ea737aca2c32dbec721942cb8671b6add6b57d3a5953389a494a28878a53abccc49de7c59bbb7e78413c3e + languageName: node + linkType: hard + +"cspell@npm:^8.3.2": + version: 8.3.2 + resolution: "cspell@npm:8.3.2" + dependencies: + "@cspell/cspell-json-reporter": 8.3.2 + "@cspell/cspell-pipe": 8.3.2 + "@cspell/cspell-types": 8.3.2 + "@cspell/dynamic-import": 8.3.2 + chalk: ^5.3.0 + chalk-template: ^1.1.0 + commander: ^11.1.0 + cspell-gitignore: 8.3.2 + cspell-glob: 8.3.2 + cspell-io: 8.3.2 + cspell-lib: 8.3.2 + fast-glob: ^3.3.2 + fast-json-stable-stringify: ^2.1.0 + file-entry-cache: ^8.0.0 + get-stdin: ^9.0.0 + semver: ^7.5.4 + strip-ansi: ^7.1.0 + vscode-uri: ^3.0.8 + bin: + cspell: bin.mjs + cspell-esm: bin.mjs + checksum: c798482b411ba94d8dc475445082d56b70fc23d88752f3e6e8e18174f247d35a0c50ed1a1a9f578cdfb1294dc8d175613f1aa7828f92b1f841047580156ab986 + languageName: node + linkType: hard + +"css-declaration-sorter@npm:^6.3.1": + version: 6.4.1 + resolution: "css-declaration-sorter@npm:6.4.1" + peerDependencies: + postcss: ^8.0.9 + checksum: cbdc9e0d481011b1a28fd5b60d4eb55fe204391d31a0b1b490b2cecf4baa85810f9b8c48adab4df644f4718104ed3ed72c64a9745e3216173767bf4aeca7f9b8 + languageName: node + linkType: hard + +"css-declaration-sorter@npm:^7.2.0": + version: 7.2.0 + resolution: "css-declaration-sorter@npm:7.2.0" + peerDependencies: + postcss: ^8.0.9 + checksum: 69b2f63a1c7c593123fabcbb353618ed01eb75f6404da9321328fbb30d603d89c47195129fadf1dc316e1406a0881400b324c2bded9438c47196e1c96ec726dd + languageName: node + linkType: hard + +"css-loader@npm:^6.7.1, css-loader@npm:^6.8.1": + version: 6.8.1 + resolution: "css-loader@npm:6.8.1" + dependencies: + icss-utils: ^5.1.0 + postcss: ^8.4.21 + postcss-modules-extract-imports: ^3.0.0 + postcss-modules-local-by-default: ^4.0.3 + postcss-modules-scope: ^3.0.0 + postcss-modules-values: ^4.0.0 + postcss-value-parser: ^4.2.0 + semver: ^7.3.8 + peerDependencies: + webpack: ^5.0.0 + checksum: 7c1784247bdbe76dc5c55fb1ac84f1d4177a74c47259942c9cfdb7a8e6baef11967a0bc85ac285f26bd26d5059decb848af8154a03fdb4f4894f41212f45eef3 + languageName: node + linkType: hard + +"css-minimizer-webpack-plugin@npm:^4.0.0": + version: 4.2.2 + resolution: "css-minimizer-webpack-plugin@npm:4.2.2" + dependencies: + cssnano: ^5.1.8 + jest-worker: ^29.1.2 + postcss: ^8.4.17 + schema-utils: ^4.0.0 + serialize-javascript: ^6.0.0 + source-map: ^0.6.1 + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + "@parcel/css": + optional: true + "@swc/css": + optional: true + clean-css: + optional: true + csso: + optional: true + esbuild: + optional: true + lightningcss: + optional: true + checksum: 5417e76a445f35832aa96807c835b8e92834a6cd285b1b788dfe3ca0fa90fec7eb2dd6efa9d3649f9d8244b99b7da2d065951603b94918e8f6a366a5049cacdd + languageName: node + linkType: hard + +"css-minimizer-webpack-plugin@npm:^5.0.1": + version: 5.0.1 + resolution: "css-minimizer-webpack-plugin@npm:5.0.1" + dependencies: + "@jridgewell/trace-mapping": ^0.3.18 + cssnano: ^6.0.1 + jest-worker: ^29.4.3 + postcss: ^8.4.24 + schema-utils: ^4.0.1 + serialize-javascript: ^6.0.1 + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + "@parcel/css": + optional: true + "@swc/css": + optional: true + clean-css: + optional: true + csso: + optional: true + esbuild: + optional: true + lightningcss: + optional: true + checksum: 10055802c61d1ae72584eac03b6bd221ecbefde11d337be44a5459d8de075b38f91b80949f95cd0c3a10295615ee013f82130bfac5fe9b5b3e8e75531f232680 + languageName: node + linkType: hard + +"css-select@npm:^4.1.3": + version: 4.3.0 + resolution: "css-select@npm:4.3.0" + dependencies: + boolbase: ^1.0.0 + css-what: ^6.0.1 + domhandler: ^4.3.1 + domutils: ^2.8.0 + nth-check: ^2.0.1 + checksum: d6202736839194dd7f910320032e7cfc40372f025e4bf21ca5bf6eb0a33264f322f50ba9c0adc35dadd342d3d6fae5ca244779a4873afbfa76561e343f2058e0 + languageName: node + linkType: hard + +"css-select@npm:^5.1.0": + version: 5.1.0 + resolution: "css-select@npm:5.1.0" + dependencies: + boolbase: ^1.0.0 + css-what: ^6.1.0 + domhandler: ^5.0.2 + domutils: ^3.0.1 + nth-check: ^2.0.1 + checksum: 2772c049b188d3b8a8159907192e926e11824aea525b8282981f72ba3f349cf9ecd523fdf7734875ee2cb772246c22117fc062da105b6d59afe8dcd5c99c9bda + languageName: node + linkType: hard + +"css-tree@npm:^1.1.2, css-tree@npm:^1.1.3": + version: 1.1.3 + resolution: "css-tree@npm:1.1.3" + dependencies: + mdn-data: 2.0.14 + source-map: ^0.6.1 + checksum: 79f9b81803991b6977b7fcb1588799270438274d89066ce08f117f5cdb5e20019b446d766c61506dd772c839df84caa16042d6076f20c97187f5abe3b50e7d1f + languageName: node + linkType: hard + +"css-tree@npm:^2.3.1": + version: 2.3.1 + resolution: "css-tree@npm:2.3.1" + dependencies: + mdn-data: 2.0.30 + source-map-js: ^1.0.1 + checksum: 493cc24b5c22b05ee5314b8a0d72d8a5869491c1458017ae5ed75aeb6c3596637dbe1b11dac2548974624adec9f7a1f3a6cf40593dc1f9185eb0e8279543fbc0 + languageName: node + linkType: hard + +"css-tree@npm:~2.2.0": + version: 2.2.1 + resolution: "css-tree@npm:2.2.1" + dependencies: + mdn-data: 2.0.28 + source-map-js: ^1.0.1 + checksum: b94aa8cc2f09e6f66c91548411fcf74badcbad3e150345074715012d16333ce573596ff5dfca03c2a87edf1924716db765120f94247e919d72753628ba3aba27 + languageName: node + linkType: hard + +"css-what@npm:^6.0.1, css-what@npm:^6.1.0": + version: 6.1.0 + resolution: "css-what@npm:6.1.0" + checksum: b975e547e1e90b79625918f84e67db5d33d896e6de846c9b584094e529f0c63e2ab85ee33b9daffd05bff3a146a1916bec664e18bb76dd5f66cbff9fc13b2bbe + languageName: node + linkType: hard + +"cssesc@npm:^3.0.0": + version: 3.0.0 + resolution: "cssesc@npm:3.0.0" + bin: + cssesc: bin/cssesc + checksum: f8c4ababffbc5e2ddf2fa9957dda1ee4af6048e22aeda1869d0d00843223c1b13ad3f5d88b51caa46c994225eacb636b764eb807a8883e2fb6f99b4f4e8c48b2 + languageName: node + linkType: hard + +"cssnano-preset-advanced@npm:^5.3.8": + version: 5.3.10 + resolution: "cssnano-preset-advanced@npm:5.3.10" + dependencies: + autoprefixer: ^10.4.12 + cssnano-preset-default: ^5.2.14 + postcss-discard-unused: ^5.1.0 + postcss-merge-idents: ^5.1.1 + postcss-reduce-idents: ^5.2.0 + postcss-zindex: ^5.1.0 + peerDependencies: + postcss: ^8.2.15 + checksum: d21cb382aea2f35c9eaa50686280bbd5158260edf73020731364b03bae0d887292da51ed0b20b369f51d2573ee8c02c695f604647b839a9ca746be8a44c3bb5b + languageName: node + linkType: hard + +"cssnano-preset-advanced@npm:^6.1.2": + version: 6.1.2 + resolution: "cssnano-preset-advanced@npm:6.1.2" + dependencies: + autoprefixer: ^10.4.19 + browserslist: ^4.23.0 + cssnano-preset-default: ^6.1.2 + postcss-discard-unused: ^6.0.5 + postcss-merge-idents: ^6.0.3 + postcss-reduce-idents: ^6.0.3 + postcss-zindex: ^6.0.2 + peerDependencies: + postcss: ^8.4.31 + checksum: cf70e27915947412730abb3075587efb66bcea58d7f1b906a7225bb4a40c9ca40150251a2ac33363d4f55bbdeb9ba000c242fa6244ee36cba2477ac07fbbe791 + languageName: node + linkType: hard + +"cssnano-preset-default@npm:^5.2.14": + version: 5.2.14 + resolution: "cssnano-preset-default@npm:5.2.14" + dependencies: + css-declaration-sorter: ^6.3.1 + cssnano-utils: ^3.1.0 + postcss-calc: ^8.2.3 + postcss-colormin: ^5.3.1 + postcss-convert-values: ^5.1.3 + postcss-discard-comments: ^5.1.2 + postcss-discard-duplicates: ^5.1.0 + postcss-discard-empty: ^5.1.1 + postcss-discard-overridden: ^5.1.0 + postcss-merge-longhand: ^5.1.7 + postcss-merge-rules: ^5.1.4 + postcss-minify-font-values: ^5.1.0 + postcss-minify-gradients: ^5.1.1 + postcss-minify-params: ^5.1.4 + postcss-minify-selectors: ^5.2.1 + postcss-normalize-charset: ^5.1.0 + postcss-normalize-display-values: ^5.1.0 + postcss-normalize-positions: ^5.1.1 + postcss-normalize-repeat-style: ^5.1.1 + postcss-normalize-string: ^5.1.0 + postcss-normalize-timing-functions: ^5.1.0 + postcss-normalize-unicode: ^5.1.1 + postcss-normalize-url: ^5.1.0 + postcss-normalize-whitespace: ^5.1.1 + postcss-ordered-values: ^5.1.3 + postcss-reduce-initial: ^5.1.2 + postcss-reduce-transforms: ^5.1.0 + postcss-svgo: ^5.1.0 + postcss-unique-selectors: ^5.1.1 + peerDependencies: + postcss: ^8.2.15 + checksum: d3bbbe3d50c6174afb28d0bdb65b511fdab33952ec84810aef58b87189f3891c34aaa8b6a6101acd5314f8acded839b43513e39a75f91a698ddc985a1b1d9e95 + languageName: node + linkType: hard + +"cssnano-preset-default@npm:^6.1.2": + version: 6.1.2 + resolution: "cssnano-preset-default@npm:6.1.2" + dependencies: + browserslist: ^4.23.0 + css-declaration-sorter: ^7.2.0 + cssnano-utils: ^4.0.2 + postcss-calc: ^9.0.1 + postcss-colormin: ^6.1.0 + postcss-convert-values: ^6.1.0 + postcss-discard-comments: ^6.0.2 + postcss-discard-duplicates: ^6.0.3 + postcss-discard-empty: ^6.0.3 + postcss-discard-overridden: ^6.0.2 + postcss-merge-longhand: ^6.0.5 + postcss-merge-rules: ^6.1.1 + postcss-minify-font-values: ^6.1.0 + postcss-minify-gradients: ^6.0.3 + postcss-minify-params: ^6.1.0 + postcss-minify-selectors: ^6.0.4 + postcss-normalize-charset: ^6.0.2 + postcss-normalize-display-values: ^6.0.2 + postcss-normalize-positions: ^6.0.2 + postcss-normalize-repeat-style: ^6.0.2 + postcss-normalize-string: ^6.0.2 + postcss-normalize-timing-functions: ^6.0.2 + postcss-normalize-unicode: ^6.1.0 + postcss-normalize-url: ^6.0.2 + postcss-normalize-whitespace: ^6.0.2 + postcss-ordered-values: ^6.0.2 + postcss-reduce-initial: ^6.1.0 + postcss-reduce-transforms: ^6.0.2 + postcss-svgo: ^6.0.3 + postcss-unique-selectors: ^6.0.4 + peerDependencies: + postcss: ^8.4.31 + checksum: 51d93e52df7141143947dc4695b5087c04b41ea153e4f4c0282ac012b62c7457c6aca244f604ae94fa3b4840903a30a1e7df38f8610e0b304d05e3065375ee56 + languageName: node + linkType: hard + +"cssnano-utils@npm:^3.1.0": + version: 3.1.0 + resolution: "cssnano-utils@npm:3.1.0" + peerDependencies: + postcss: ^8.2.15 + checksum: 975c84ce9174cf23bb1da1e9faed8421954607e9ea76440cd3bb0c1bea7e17e490d800fca5ae2812d1d9e9d5524eef23ede0a3f52497d7ccc628e5d7321536f2 + languageName: node + linkType: hard + +"cssnano-utils@npm:^4.0.2": + version: 4.0.2 + resolution: "cssnano-utils@npm:4.0.2" + peerDependencies: + postcss: ^8.4.31 + checksum: f04c6854e75d847c7a43aff835e003d5bc7387ddfc476f0ad3a2d63663d0cec41047d46604c1717bf6b5a8e24e54bb519e465ff78d62c7e073c7cbe2279bebaf + languageName: node + linkType: hard + +"cssnano@npm:^5.1.12, cssnano@npm:^5.1.8": + version: 5.1.15 + resolution: "cssnano@npm:5.1.15" + dependencies: + cssnano-preset-default: ^5.2.14 + lilconfig: ^2.0.3 + yaml: ^1.10.2 + peerDependencies: + postcss: ^8.2.15 + checksum: ca9e1922178617c66c2f1548824b2c7af2ecf69cc3a187fc96bf8d29251c2e84d9e4966c69cf64a2a6a057a37dff7d6d057bc8a2a0957e6ea382e452ae9d0bbb + languageName: node + linkType: hard + +"cssnano@npm:^6.0.1, cssnano@npm:^6.1.2": + version: 6.1.2 + resolution: "cssnano@npm:6.1.2" + dependencies: + cssnano-preset-default: ^6.1.2 + lilconfig: ^3.1.1 + peerDependencies: + postcss: ^8.4.31 + checksum: 65aad92c5ee0089ffd4cd933c18c65edbf7634f7c3cd833a499dc948aa7e4168be22130dfe83bde07fcdc87f7c45a02d09040b7f439498208bc90b8d5a9abcc8 + languageName: node + linkType: hard + +"csso@npm:^4.2.0": + version: 4.2.0 + resolution: "csso@npm:4.2.0" + dependencies: + css-tree: ^1.1.2 + checksum: 380ba9663da3bcea58dee358a0d8c4468bb6539be3c439dc266ac41c047217f52fd698fb7e4b6b6ccdfb8cf53ef4ceed8cc8ceccb8dfca2aa628319826b5b998 + languageName: node + linkType: hard + +"csso@npm:^5.0.5": + version: 5.0.5 + resolution: "csso@npm:5.0.5" + dependencies: + css-tree: ~2.2.0 + checksum: 0ad858d36bf5012ed243e9ec69962a867509061986d2ee07cc040a4b26e4d062c00d4c07e5ba8d430706ceb02dd87edd30a52b5937fd45b1b6f2119c4993d59a + languageName: node + linkType: hard + +"csstype@npm:^3.0.2": + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 8db785cc92d259102725b3c694ec0c823f5619a84741b5c7991b8ad135dfaa66093038a1cc63e03361a6cd28d122be48f2106ae72334e067dd619a51f49eddf7 + languageName: node + linkType: hard + +"data-uri-to-buffer@npm:^6.0.0": + version: 6.0.1 + resolution: "data-uri-to-buffer@npm:6.0.1" + checksum: 9140e68c585ae33d950f5943bd476751346c8b789ae80b01a578a33cb8f7f706d1ca7378aff2b1878b2a6d9a8c88c55cc286d88191c8b8ead8255c3c4d934530 + languageName: node + linkType: hard + +"debounce@npm:^1.2.0, debounce@npm:^1.2.1": + version: 1.2.1 + resolution: "debounce@npm:1.2.1" + checksum: 682a89506d9e54fb109526f4da255c5546102fbb8e3ae75eef3b04effaf5d4853756aee97475cd4650641869794e44f410eeb20ace2b18ea592287ab2038519e + languageName: node + linkType: hard + +"debug@npm:2.6.9, debug@npm:^2.6.0, debug@npm:^2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: 2.0.0 + checksum: d2f51589ca66df60bf36e1fa6e4386b318c3f1e06772280eea5b1ae9fd3d05e9c2b7fd8a7d862457d00853c75b00451aa2d7459b924629ee385287a650f58fe6 + 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.1, debug@npm:^4.3.2, debug@npm:^4.3.4": + version: 4.3.4 + resolution: "debug@npm:4.3.4" + dependencies: + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 + languageName: node + linkType: hard + +"debug@npm:^3.1.0, debug@npm:^3.2.7": + version: 3.2.7 + resolution: "debug@npm:3.2.7" + dependencies: + ms: ^2.1.1 + checksum: b3d8c5940799914d30314b7c3304a43305fd0715581a919dacb8b3176d024a782062368405b47491516d2091d6462d4d11f2f4974a405048094f8bfebfa3071c + languageName: node + linkType: hard + +"decamelize@npm:^4.0.0": + version: 4.0.0 + resolution: "decamelize@npm:4.0.0" + checksum: b7d09b82652c39eead4d6678bb578e3bebd848add894b76d0f6b395bc45b2d692fb88d977e7cfb93c4ed6c119b05a1347cef261174916c2e75c0a8ca57da1809 + languageName: node + linkType: hard + +"decode-named-character-reference@npm:^1.0.0": + version: 1.0.2 + resolution: "decode-named-character-reference@npm:1.0.2" + dependencies: + character-entities: ^2.0.0 + checksum: f4c71d3b93105f20076052f9cb1523a22a9c796b8296cd35eef1ca54239c78d182c136a848b83ff8da2071e3ae2b1d300bf29d00650a6d6e675438cc31b11d78 + languageName: node + linkType: hard + +"decompress-response@npm:^3.3.0": + version: 3.3.0 + resolution: "decompress-response@npm:3.3.0" + dependencies: + mimic-response: ^1.0.0 + checksum: 952552ac3bd7de2fc18015086b09468645c9638d98a551305e485230ada278c039c91116e946d07894b39ee53c0f0d5b6473f25a224029344354513b412d7380 + languageName: node + linkType: hard + +"decompress-response@npm:^6.0.0": + version: 6.0.0 + resolution: "decompress-response@npm:6.0.0" + dependencies: + mimic-response: ^3.1.0 + checksum: d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 + languageName: node + linkType: hard + +"deep-eql@npm:^4.0.1, deep-eql@npm:^4.1.3": + version: 4.1.3 + resolution: "deep-eql@npm:4.1.3" + dependencies: + type-detect: ^4.0.0 + checksum: 7f6d30cb41c713973dc07eaadded848b2ab0b835e518a88b91bea72f34e08c4c71d167a722a6f302d3a6108f05afd8e6d7650689a84d5d29ec7fe6220420397f + languageName: node + linkType: hard + +"deep-equal@npm:~1.0.1": + version: 1.0.1 + resolution: "deep-equal@npm:1.0.1" + checksum: 5af8cbfcebf190491878a498caccc7dc9592f8ebd1685b976eacc3825619d222b5e929923163b92c4f414494e2b884f7ebf00c022e8198e8292deb70dd9785f4 + languageName: node + linkType: hard + +"deep-extend@npm:^0.6.0, deep-extend@npm:~0.6.0": + version: 0.6.0 + resolution: "deep-extend@npm:0.6.0" + checksum: 7be7e5a8d468d6b10e6a67c3de828f55001b6eb515d014f7aeb9066ce36bd5717161eb47d6a0f7bed8a9083935b465bc163ee2581c8b128d29bf61092fdf57a7 + languageName: node + linkType: hard + +"deep-is@npm:^0.1.3": + version: 0.1.4 + resolution: "deep-is@npm:0.1.4" + checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 + languageName: node + linkType: hard + +"deepmerge@npm:^4.2.2, deepmerge@npm:^4.3.1": + version: 4.3.1 + resolution: "deepmerge@npm:4.3.1" + checksum: 2024c6a980a1b7128084170c4cf56b0fd58a63f2da1660dcfe977415f27b17dbe5888668b59d0b063753f3220719d5e400b7f113609489c90160bb9a5518d052 + languageName: node + linkType: hard + +"default-browser-id@npm:^5.0.0": + version: 5.0.0 + resolution: "default-browser-id@npm:5.0.0" + checksum: 185bfaecec2c75fa423544af722a3469b20704c8d1942794a86e4364fe7d9e8e9f63241a5b769d61c8151993bc65833a5b959026fa1ccea343b3db0a33aa6deb + languageName: node + linkType: hard + +"default-browser@npm:^5.2.1": + version: 5.2.1 + resolution: "default-browser@npm:5.2.1" + dependencies: + bundle-name: ^4.1.0 + default-browser-id: ^5.0.0 + checksum: afab7eff7b7f5f7a94d9114d1ec67273d3fbc539edf8c0f80019879d53aa71e867303c6f6d7cffeb10a6f3cfb59d4f963dba3f9c96830b4540cc7339a1bf9840 + languageName: node + linkType: hard + +"default-gateway@npm:^6.0.3": + version: 6.0.3 + resolution: "default-gateway@npm:6.0.3" + dependencies: + execa: ^5.0.0 + checksum: 126f8273ecac8ee9ff91ea778e8784f6cd732d77c3157e8c5bdd6ed03651b5291f71446d05bc02d04073b1e67583604db5394ea3cf992ede0088c70ea15b7378 + languageName: node + linkType: hard + +"defer-to-connect@npm:^1.0.1": + version: 1.1.3 + resolution: "defer-to-connect@npm:1.1.3" + checksum: 9491b301dcfa04956f989481ba7a43c2231044206269eb4ab64a52d6639ee15b1252262a789eb4239fb46ab63e44d4e408641bae8e0793d640aee55398cb3930 + languageName: node + linkType: hard + +"defer-to-connect@npm:^2.0.1": + version: 2.0.1 + resolution: "defer-to-connect@npm:2.0.1" + checksum: 8a9b50d2f25446c0bfefb55a48e90afd58f85b21bcf78e9207cd7b804354f6409032a1705c2491686e202e64fc05f147aa5aa45f9aa82627563f045937f5791b + languageName: node + linkType: hard + +"deferred-leveldown@npm:~0.2.0": + version: 0.2.0 + resolution: "deferred-leveldown@npm:0.2.0" + dependencies: + abstract-leveldown: ~0.12.1 + checksum: f7690ec5b1e951e6f56998be26dd0a1331ef28cb7eaa9e090a282780d47dc006effd4b82a2a82b636cae801378047997aca10c0b44b09c8624633cdb96b07913 + languageName: node + linkType: hard + +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": + version: 1.1.1 + resolution: "define-data-property@npm:1.1.1" + dependencies: + get-intrinsic: ^1.2.1 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + checksum: a29855ad3f0630ea82e3c5012c812efa6ca3078d5c2aa8df06b5f597c1cde6f7254692df41945851d903e05a1668607b6d34e778f402b9ff9ffb38111f1a3f0d + languageName: node + linkType: hard + +"define-lazy-prop@npm:^2.0.0": + version: 2.0.0 + resolution: "define-lazy-prop@npm:2.0.0" + checksum: 0115fdb065e0490918ba271d7339c42453d209d4cb619dfe635870d906731eff3e1ade8028bb461ea27ce8264ec5e22c6980612d332895977e89c1bbc80fcee2 + languageName: node + linkType: hard + +"define-lazy-prop@npm:^3.0.0": + version: 3.0.0 + resolution: "define-lazy-prop@npm:3.0.0" + checksum: 54884f94caac0791bf6395a3ec530ce901cf71c47b0196b8754f3fd17edb6c0e80149c1214429d851873bb0d689dbe08dcedbb2306dc45c8534a5934723851b6 + languageName: node + linkType: hard + +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.1": + version: 1.2.1 + resolution: "define-properties@npm:1.2.1" + dependencies: + define-data-property: ^1.0.1 + has-property-descriptors: ^1.0.0 + object-keys: ^1.1.1 + checksum: b4ccd00597dd46cb2d4a379398f5b19fca84a16f3374e2249201992f36b30f6835949a9429669ee6b41b6e837205a163eadd745e472069e70dfc10f03e5fcc12 + languageName: node + linkType: hard + +"degenerator@npm:^5.0.0": + version: 5.0.1 + resolution: "degenerator@npm:5.0.1" + dependencies: + ast-types: ^0.13.4 + escodegen: ^2.1.0 + esprima: ^4.0.1 + checksum: a64fa39cdf6c2edd75188157d32338ee9de7193d7dbb2aeb4acb1eb30fa4a15ed80ba8dae9bd4d7b085472cf174a5baf81adb761aaa8e326771392c922084152 + languageName: node + linkType: hard + +"del@npm:^6.1.1": + version: 6.1.1 + resolution: "del@npm:6.1.1" + dependencies: + globby: ^11.0.1 + graceful-fs: ^4.2.4 + is-glob: ^4.0.1 + is-path-cwd: ^2.2.0 + is-path-inside: ^3.0.2 + p-map: ^4.0.0 + rimraf: ^3.0.2 + slash: ^3.0.0 + checksum: 563288b73b8b19a7261c47fd21a330eeab6e2acd7c6208c49790dfd369127120dd7836cdf0c1eca216b77c94782a81507eac6b4734252d3bef2795cb366996b6 + languageName: node + linkType: hard + +"delayed-stream@npm:~1.0.0": + version: 1.0.0 + resolution: "delayed-stream@npm:1.0.0" + checksum: 46fe6e83e2cb1d85ba50bd52803c68be9bd953282fa7096f51fc29edd5d67ff84ff753c51966061e5ba7cb5e47ef6d36a91924eddb7f3f3483b1c560f77a0020 + languageName: node + linkType: hard + +"delegates@npm:^1.0.0": + version: 1.0.0 + resolution: "delegates@npm:1.0.0" + checksum: a51744d9b53c164ba9c0492471a1a2ffa0b6727451bdc89e31627fdf4adda9d51277cfcbfb20f0a6f08ccb3c436f341df3e92631a3440226d93a8971724771fd + languageName: node + linkType: hard + +"depd@npm:2.0.0, depd@npm:^2.0.0, depd@npm:~2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: abbe19c768c97ee2eed6282d8ce3031126662252c58d711f646921c9623f9052e3e1906443066beec1095832f534e57c523b7333f8e7e0d93051ab6baef5ab3a + languageName: node + linkType: hard + +"depd@npm:~1.1.2": + version: 1.1.2 + resolution: "depd@npm:1.1.2" + checksum: 6b406620d269619852885ce15965272b829df6f409724415e0002c8632ab6a8c0a08ec1f0bd2add05dc7bd7507606f7e2cc034fa24224ab829580040b835ecd9 + languageName: node + linkType: hard + +"dependency-graph@npm:^0.11.0": + version: 0.11.0 + resolution: "dependency-graph@npm:0.11.0" + checksum: 477204beaa9be69e642bc31ffe7a8c383d0cf48fa27acbc91c5df01431ab913e65c154213d2ef83d034c98d77280743ec85e5da018a97a18dd43d3c0b78b28cd + languageName: node + linkType: hard + +"dequal@npm:^2.0.0": + version: 2.0.3 + resolution: "dequal@npm:2.0.3" + checksum: 8679b850e1a3d0ebbc46ee780d5df7b478c23f335887464023a631d1b9af051ad4a6595a44220f9ff8ff95a8ddccf019b5ad778a976fd7bbf77383d36f412f90 + languageName: node + linkType: hard + +"destroy@npm:1.2.0, destroy@npm:^1.0.4": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 + languageName: node + linkType: hard + +"detab@npm:2.0.4": + version: 2.0.4 + resolution: "detab@npm:2.0.4" + dependencies: + repeat-string: ^1.5.4 + checksum: 34b077521ecd4c6357d32ff7923be644d34aa6f6b7d717d40ec4a9168243eefaea2b512a75a460a6f70c31b0bbc31ff90f820a891803b4ddaf99e9d04d0d389d + languageName: node + linkType: hard + +"detect-node@npm:^2.0.4": + version: 2.1.0 + resolution: "detect-node@npm:2.1.0" + checksum: 832184ec458353e41533ac9c622f16c19f7c02d8b10c303dfd3a756f56be93e903616c0bb2d4226183c9351c15fc0b3dba41a17a2308262afabcfa3776e6ae6e + languageName: node + linkType: hard + +"detect-port-alt@npm:^1.1.6": + version: 1.1.6 + resolution: "detect-port-alt@npm:1.1.6" + dependencies: + address: ^1.0.1 + debug: ^2.6.0 + bin: + detect: ./bin/detect-port + detect-port: ./bin/detect-port + checksum: 9dc37b1fa4a9dd6d4889e1045849b8d841232b598d1ca888bf712f4035b07a17cf6d537465a0d7323250048d3a5a0540e3b7cf89457efc222f96f77e2c40d16a + languageName: node + linkType: hard + +"detect-port@npm:^1.3.0, detect-port@npm:^1.5.1": + version: 1.5.1 + resolution: "detect-port@npm:1.5.1" + dependencies: + address: ^1.0.1 + debug: 4 + bin: + detect: bin/detect-port.js + detect-port: bin/detect-port.js + checksum: b48da9340481742547263d5d985e65d078592557863402ecf538511735e83575867e94f91fe74405ea19b61351feb99efccae7e55de9a151d5654e3417cea05b + languageName: node + linkType: hard + +"devlop@npm:^1.0.0, devlop@npm:^1.1.0": + version: 1.1.0 + resolution: "devlop@npm:1.1.0" + dependencies: + dequal: ^2.0.0 + checksum: d2ff650bac0bb6ef08c48f3ba98640bb5fec5cce81e9957eb620408d1bab1204d382a45b785c6b3314dc867bb0684936b84c6867820da6db97cbb5d3c15dd185 + languageName: node + linkType: hard + +"devtools-protocol@npm:0.0.1249869": + version: 0.0.1249869 + resolution: "devtools-protocol@npm:0.0.1249869" + checksum: 549dda02f6d778741930e5abdde3f8e5d39e16fdbe8af38597a974e9c239798dd464250bd7ab4360d77e3d059620e95be7cf05150142473bf9b661ed28a616ed + languageName: node + linkType: hard + +"diff@npm:5.0.0": + version: 5.0.0 + resolution: "diff@npm:5.0.0" + checksum: f19fe29284b633afdb2725c2a8bb7d25761ea54d321d8e67987ac851c5294be4afeab532bd84531e02583a3fe7f4014aa314a3eda84f5590e7a9e6b371ef3b46 + languageName: node + linkType: hard + +"diff@npm:^4.0.1": + version: 4.0.2 + resolution: "diff@npm:4.0.2" + checksum: f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d + languageName: node + linkType: hard + +"diff@npm:^5.0.0, diff@npm:^5.1.0": + version: 5.1.0 + resolution: "diff@npm:5.1.0" + checksum: c7bf0df7c9bfbe1cf8a678fd1b2137c4fb11be117a67bc18a0e03ae75105e8533dbfb1cda6b46beb3586ef5aed22143ef9d70713977d5fb1f9114e21455fba90 + languageName: node + linkType: hard + +"dir-glob@npm:^3.0.1": + version: 3.0.1 + resolution: "dir-glob@npm:3.0.1" + dependencies: + path-type: ^4.0.0 + checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 + languageName: node + linkType: hard + +"dns-equal@npm:^1.0.0": + version: 1.0.0 + resolution: "dns-equal@npm:1.0.0" + checksum: a8471ac849c7c13824f053babea1bc26e2f359394dd5a460f8340d8abd13434be01e3327a5c59d212f8c8997817450efd3f3ac77bec709b21979cf0235644524 + languageName: node + linkType: hard + +"dns-packet@npm:^5.2.2": + version: 5.6.1 + resolution: "dns-packet@npm:5.6.1" + dependencies: + "@leichtgewicht/ip-codec": ^2.0.1 + checksum: 64c06457f0c6e143f7a0946e0aeb8de1c5f752217cfa143ef527467c00a6d78db1835cfdb6bb68333d9f9a4963cf23f410439b5262a8935cce1236f45e344b81 + languageName: node + linkType: hard + +"docs@workspace:docs": + version: 0.0.0-use.local + resolution: "docs@workspace:docs" + dependencies: + "@docusaurus/core": ^3.5.2 + "@docusaurus/module-type-aliases": ^3.5.2 + "@docusaurus/preset-classic": ^3.5.2 + "@docusaurus/tsconfig": ^3.5.2 + "@docusaurus/types": ^3.5.2 + "@easyops-cn/docusaurus-search-local": ^0.35.0 + "@mdx-js/react": ^3.0.0 + "@noir-lang/noir_js": "workspace:*" + "@noir-lang/noirc_abi": "workspace:*" + "@noir-lang/types": "workspace:*" + "@types/prettier": ^3 + axios: ^1.4.0 + clsx: ^1.2.1 + docusaurus-plugin-typedoc: 1.0.0-next.18 + eslint-plugin-prettier: ^5.1.3 + hast-util-is-element: ^1.1.0 + prettier: 3.2.5 + prism-react-renderer: ^2.1.0 + react: ^18.2.0 + react-dom: ^18.2.0 + react-spinners: ^0.13.8 + rehype-katex: ^7.0.0 + remark-math: ^6.0.0 + serve: ^14.2.1 + ts-node: ^10.9.1 + typedoc: ^0.25.0 + typedoc-plugin-frontmatter: ^0.0.2 + typedoc-plugin-markdown: 4.0.0-next.25 + typedoc-plugin-merge-modules: ^5.1.0 + typescript: ^5.4.2 + languageName: unknown + linkType: soft + +"doctrine@npm:^3.0.0": + version: 3.0.0 + resolution: "doctrine@npm:3.0.0" + dependencies: + esutils: ^2.0.2 + checksum: fd7673ca77fe26cd5cba38d816bc72d641f500f1f9b25b83e8ce28827fe2da7ad583a8da26ab6af85f834138cf8dae9f69b0cd6ab925f52ddab1754db44d99ce + languageName: node + linkType: hard + +"docusaurus-plugin-typedoc@npm:1.0.0-next.18": + version: 1.0.0-next.18 + resolution: "docusaurus-plugin-typedoc@npm:1.0.0-next.18" + dependencies: + "@docusaurus/types": ^2.4.1 + peerDependencies: + typedoc-plugin-markdown: ">=4.0.0-next.24" + checksum: a501e3bd1cc5b33d215a1b71b018a34d4aa5bd98f39580ab114a127d3f555078443d6b690119c0adb17fb8867ba4131382ad5d14dbaa7919715020cdfaf6b9c4 + languageName: node + linkType: hard + +"dom-converter@npm:^0.2.0": + version: 0.2.0 + resolution: "dom-converter@npm:0.2.0" + dependencies: + utila: ~0.4 + checksum: ea52fe303f5392e48dea563abef0e6fb3a478b8dbe3c599e99bb5d53981c6c38fc4944e56bb92a8ead6bb989d10b7914722ae11febbd2fd0910e33b9fc4aaa77 + languageName: node + linkType: hard + +"dom-serializer@npm:^1.0.1": + version: 1.4.1 + resolution: "dom-serializer@npm:1.4.1" + dependencies: + domelementtype: ^2.0.1 + domhandler: ^4.2.0 + entities: ^2.0.0 + checksum: fbb0b01f87a8a2d18e6e5a388ad0f7ec4a5c05c06d219377da1abc7bb0f674d804f4a8a94e3f71ff15f6cb7dcfc75704a54b261db672b9b3ab03da6b758b0b22 + languageName: node + linkType: hard + +"dom-serializer@npm:^2.0.0": + version: 2.0.0 + resolution: "dom-serializer@npm:2.0.0" + dependencies: + domelementtype: ^2.3.0 + domhandler: ^5.0.2 + entities: ^4.2.0 + checksum: cd1810544fd8cdfbd51fa2c0c1128ec3a13ba92f14e61b7650b5de421b88205fd2e3f0cc6ace82f13334114addb90ed1c2f23074a51770a8e9c1273acbc7f3e6 + languageName: node + linkType: hard + +"domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0, domelementtype@npm:^2.3.0": + version: 2.3.0 + resolution: "domelementtype@npm:2.3.0" + checksum: ee837a318ff702622f383409d1f5b25dd1024b692ef64d3096ff702e26339f8e345820f29a68bcdcea8cfee3531776b3382651232fbeae95612d6f0a75efb4f6 + languageName: node + linkType: hard + +"domhandler@npm:^4.0.0, domhandler@npm:^4.2.0, domhandler@npm:^4.3.1": + version: 4.3.1 + resolution: "domhandler@npm:4.3.1" + dependencies: + domelementtype: ^2.2.0 + checksum: 4c665ceed016e1911bf7d1dadc09dc888090b64dee7851cccd2fcf5442747ec39c647bb1cb8c8919f8bbdd0f0c625a6bafeeed4b2d656bbecdbae893f43ffaaa + languageName: node + linkType: hard + +"domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": + version: 5.0.3 + resolution: "domhandler@npm:5.0.3" + dependencies: + domelementtype: ^2.3.0 + checksum: 0f58f4a6af63e6f3a4320aa446d28b5790a009018707bce2859dcb1d21144c7876482b5188395a188dfa974238c019e0a1e610d2fc269a12b2c192ea2b0b131c + languageName: node + linkType: hard + +"domutils@npm:^2.5.2, domutils@npm:^2.8.0": + version: 2.8.0 + resolution: "domutils@npm:2.8.0" + dependencies: + dom-serializer: ^1.0.1 + domelementtype: ^2.2.0 + domhandler: ^4.2.0 + checksum: abf7434315283e9aadc2a24bac0e00eab07ae4313b40cc239f89d84d7315ebdfd2fb1b5bf750a96bc1b4403d7237c7b2ebf60459be394d625ead4ca89b934391 + languageName: node + linkType: hard + +"domutils@npm:^3.0.1": + version: 3.1.0 + resolution: "domutils@npm:3.1.0" + dependencies: + dom-serializer: ^2.0.0 + domelementtype: ^2.3.0 + domhandler: ^5.0.3 + checksum: e5757456ddd173caa411cfc02c2bb64133c65546d2c4081381a3bafc8a57411a41eed70494551aa58030be9e58574fcc489828bebd673863d39924fb4878f416 + languageName: node + linkType: hard + +"dot-case@npm:^3.0.4": + version: 3.0.4 + resolution: "dot-case@npm:3.0.4" + dependencies: + no-case: ^3.0.4 + tslib: ^2.0.3 + checksum: a65e3519414856df0228b9f645332f974f2bf5433370f544a681122eab59e66038fc3349b4be1cdc47152779dac71a5864f1ccda2f745e767c46e9c6543b1169 + languageName: node + linkType: hard + +"dot-prop@npm:^5.2.0": + version: 5.3.0 + resolution: "dot-prop@npm:5.3.0" + dependencies: + is-obj: ^2.0.0 + checksum: d5775790093c234ef4bfd5fbe40884ff7e6c87573e5339432870616331189f7f5d86575c5b5af2dcf0f61172990f4f734d07844b1f23482fff09e3c4bead05ea + languageName: node + linkType: hard + +"dot-prop@npm:^6.0.1": + version: 6.0.1 + resolution: "dot-prop@npm:6.0.1" + dependencies: + is-obj: ^2.0.0 + checksum: 0f47600a4b93e1dc37261da4e6909652c008832a5d3684b5bf9a9a0d3f4c67ea949a86dceed9b72f5733ed8e8e6383cc5958df3bbd0799ee317fd181f2ece700 + languageName: node + linkType: hard + +"duplexer3@npm:^0.1.4": + version: 0.1.5 + resolution: "duplexer3@npm:0.1.5" + checksum: e677cb4c48f031ca728601d6a20bf6aed4c629d69ef9643cb89c67583d673c4ec9317cc6427501f38bd8c368d3a18f173987cc02bd99d8cf8fe3d94259a22a20 + languageName: node + linkType: hard + +"duplexer@npm:^0.1.2": + version: 0.1.2 + resolution: "duplexer@npm:0.1.2" + checksum: 62ba61a830c56801db28ff6305c7d289b6dc9f859054e8c982abd8ee0b0a14d2e9a8e7d086ffee12e868d43e2bbe8a964be55ddbd8c8957714c87373c7a4f9b0 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 7d00d7cd8e49b9afa762a813faac332dee781932d6f2c848dc348939c4253f1d4564341b7af1d041853bc3f32c2ef141b58e0a4d9862c17a7f08f68df1e0f1ed + languageName: node + linkType: hard + +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 1b4cac778d64ce3b582a7e26b218afe07e207a0f9bfe13cc7395a6d307849cfe361e65033c3251e00c27dd060cab43014c2d6b2647676135e18b77d2d05b3f4f + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.4.601": + version: 1.4.609 + resolution: "electron-to-chromium@npm:1.4.609" + checksum: 4ef3c32b11adc01ed8227d7bdbe0978b436b817e6b3bd09f19b42afbf9affdb6ddf99f4d20a3b28a494772a2985df12ec95abca849a38cccb217c4ee338561bb + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.5.28": + version: 1.5.29 + resolution: "electron-to-chromium@npm:1.5.29" + checksum: c1de62aaea88c9b3ba32f8f2703b9d77a81633099a8f61365eaf9855d36e72189dcd99b9c3b8b2804afa403ac2ce0b00c23affa6f19d17b04ce0076f66a546b6 + languageName: node + linkType: hard + +"elliptic@npm:6.5.4, elliptic@npm:^6.5.2, elliptic@npm:^6.5.4": + version: 6.5.4 + resolution: "elliptic@npm:6.5.4" + dependencies: + bn.js: ^4.11.9 + brorand: ^1.1.0 + hash.js: ^1.0.0 + hmac-drbg: ^1.0.1 + inherits: ^2.0.4 + minimalistic-assert: ^1.0.1 + minimalistic-crypto-utils: ^1.0.1 + checksum: d56d21fd04e97869f7ffcc92e18903b9f67f2d4637a23c860492fbbff5a3155fd9ca0184ce0c865dd6eb2487d234ce9551335c021c376cd2d3b7cb749c7d10f4 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 + languageName: node + linkType: hard + +"emojilib@npm:^2.4.0": + version: 2.4.0 + resolution: "emojilib@npm:2.4.0" + checksum: ea241c342abda5a86ffd3a15d8f4871a616d485f700e03daea38c6ce38205847cea9f6ff8d5e962c00516b004949cc96c6e37b05559ea71a0a496faba53b56da + languageName: node + linkType: hard + +"emojis-list@npm:^3.0.0": + version: 3.0.0 + resolution: "emojis-list@npm:3.0.0" + checksum: ddaaa02542e1e9436c03970eeed445f4ed29a5337dfba0fe0c38dfdd2af5da2429c2a0821304e8a8d1cadf27fdd5b22ff793571fa803ae16852a6975c65e8e70 + languageName: node + linkType: hard + +"emoticon@npm:^3.2.0": + version: 3.2.0 + resolution: "emoticon@npm:3.2.0" + checksum: f30649d18b672ab3139e95cb04f77b2442feb95c99dc59372ff80fbfd639b2bf4018bc68ab0b549bd765aecf8230d7899c43f86cfcc7b6370c06c3232783e24f + languageName: node + linkType: hard + +"emoticon@npm:^4.0.1": + version: 4.0.1 + resolution: "emoticon@npm:4.0.1" + checksum: 991ab6421927601af4eb44036b60e3125759a4d81f32d2ad96b66e3491e2fdb6a026eeb6bffbfa66724592dca95235570785963607d16961ea73a62ecce715e2 + languageName: node + linkType: hard + +"encodeurl@npm:^1.0.2, encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: ^0.6.2 + checksum: bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f + languageName: node + linkType: hard + +"end-of-stream@npm:^1.1.0": + version: 1.4.4 + resolution: "end-of-stream@npm:1.4.4" + dependencies: + once: ^1.4.0 + checksum: 530a5a5a1e517e962854a31693dbb5c0b2fc40b46dad2a56a2deec656ca040631124f4795823acc68238147805f8b021abbe221f4afed5ef3c8e8efc2024908b + languageName: node + linkType: hard + +"enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.15.0": + version: 5.15.0 + resolution: "enhanced-resolve@npm:5.15.0" + dependencies: + graceful-fs: ^4.2.4 + tapable: ^2.2.0 + checksum: fbd8cdc9263be71cc737aa8a7d6c57b43d6aa38f6cc75dde6fcd3598a130cc465f979d2f4d01bb3bf475acb43817749c79f8eef9be048683602ca91ab52e4f11 + languageName: node + linkType: hard + +"enquirer@npm:^2.3.0": + version: 2.4.1 + resolution: "enquirer@npm:2.4.1" + dependencies: + ansi-colors: ^4.1.1 + strip-ansi: ^6.0.1 + checksum: f080f11a74209647dbf347a7c6a83c8a47ae1ebf1e75073a808bc1088eb780aa54075bfecd1bcdb3e3c724520edb8e6ee05da031529436b421b71066fcc48cb5 + languageName: node + linkType: hard + +"entities@npm:^2.0.0": + version: 2.2.0 + resolution: "entities@npm:2.2.0" + checksum: 19010dacaf0912c895ea262b4f6128574f9ccf8d4b3b65c7e8334ad0079b3706376360e28d8843ff50a78aabcb8f08f0a32dbfacdc77e47ed77ca08b713669b3 + languageName: node + linkType: hard + +"entities@npm:^4.2.0, entities@npm:^4.4.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 853f8ebd5b425d350bffa97dd6958143179a5938352ccae092c62d1267c4e392a039be1bae7d51b6e4ffad25f51f9617531fedf5237f15df302ccfb452cbf2d7 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e + languageName: node + linkType: hard + +"envinfo@npm:^7.7.3": + version: 7.11.0 + resolution: "envinfo@npm:7.11.0" + bin: + envinfo: dist/cli.js + checksum: c45a7d20409d5f4cda72483b150d3816b15b434f2944d72c1495d8838bd7c4e7b2f32c12128ffb9b92b5f66f436237b8a525eb3a9a5da2d20013bc4effa28aef + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 8b7b1be20d2de12d2255c0bc2ca638b7af5171142693299416e6a9339bd7d88fc8d7707d913d78e0993176005405a236b066b45666b27b797252c771156ace54 + languageName: node + linkType: hard + +"errno@npm:^0.1.1, errno@npm:~0.1.1": + version: 0.1.8 + resolution: "errno@npm:0.1.8" + dependencies: + prr: ~1.0.1 + bin: + errno: cli.js + checksum: 1271f7b9fbb3bcbec76ffde932485d1e3561856d21d847ec613a9722ee924cdd4e523a62dc71a44174d91e898fe21fdc8d5b50823f4b5e0ce8c35c8271e6ef4a + languageName: node + linkType: hard + +"error-ex@npm:^1.3.1": + version: 1.3.2 + resolution: "error-ex@npm:1.3.2" + dependencies: + is-arrayish: ^0.2.1 + checksum: c1c2b8b65f9c91b0f9d75f0debaa7ec5b35c266c2cac5de412c1a6de86d4cbae04ae44e510378cb14d032d0645a36925d0186f8bb7367bcc629db256b743a001 + languageName: node + linkType: hard + +"errorstacks@npm:^2.2.0": + version: 2.4.1 + resolution: "errorstacks@npm:2.4.1" + checksum: 1b46bdd3c40d3e30dbb6945c0529ffbef6ccdf2260eeecff6cc1ee95b708ec732094597d6adaa53ffe18d045150b366e3f7472d8594946f430941bfa4ad54479 + languageName: node + linkType: hard + +"es-module-lexer@npm:^1.0.0, es-module-lexer@npm:^1.2.1": + version: 1.4.1 + resolution: "es-module-lexer@npm:1.4.1" + checksum: a11b5a256d4e8e9c7d94c2fd87415ccd1591617b6edd847e064503f8eaece2d25e2e9078a02c5ce3ed5e83bb748f5b4820efbe78072c8beb07ac619c2edec35d + languageName: node + linkType: hard + +"esbuild@npm:^0.16 || ^0.17": + version: 0.17.19 + resolution: "esbuild@npm:0.17.19" + dependencies: + "@esbuild/android-arm": 0.17.19 + "@esbuild/android-arm64": 0.17.19 + "@esbuild/android-x64": 0.17.19 + "@esbuild/darwin-arm64": 0.17.19 + "@esbuild/darwin-x64": 0.17.19 + "@esbuild/freebsd-arm64": 0.17.19 + "@esbuild/freebsd-x64": 0.17.19 + "@esbuild/linux-arm": 0.17.19 + "@esbuild/linux-arm64": 0.17.19 + "@esbuild/linux-ia32": 0.17.19 + "@esbuild/linux-loong64": 0.17.19 + "@esbuild/linux-mips64el": 0.17.19 + "@esbuild/linux-ppc64": 0.17.19 + "@esbuild/linux-riscv64": 0.17.19 + "@esbuild/linux-s390x": 0.17.19 + "@esbuild/linux-x64": 0.17.19 + "@esbuild/netbsd-x64": 0.17.19 + "@esbuild/openbsd-x64": 0.17.19 + "@esbuild/sunos-x64": 0.17.19 + "@esbuild/win32-arm64": 0.17.19 + "@esbuild/win32-ia32": 0.17.19 + "@esbuild/win32-x64": 0.17.19 + dependenciesMeta: + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: ac11b1a5a6008e4e37ccffbd6c2c054746fc58d0ed4a2f9ee643bd030cfcea9a33a235087bc777def8420f2eaafb3486e76adb7bdb7241a9143b43a69a10afd8 + languageName: node + linkType: hard + +"esbuild@npm:~0.18.20": + version: 0.18.20 + resolution: "esbuild@npm:0.18.20" + dependencies: + "@esbuild/android-arm": 0.18.20 + "@esbuild/android-arm64": 0.18.20 + "@esbuild/android-x64": 0.18.20 + "@esbuild/darwin-arm64": 0.18.20 + "@esbuild/darwin-x64": 0.18.20 + "@esbuild/freebsd-arm64": 0.18.20 + "@esbuild/freebsd-x64": 0.18.20 + "@esbuild/linux-arm": 0.18.20 + "@esbuild/linux-arm64": 0.18.20 + "@esbuild/linux-ia32": 0.18.20 + "@esbuild/linux-loong64": 0.18.20 + "@esbuild/linux-mips64el": 0.18.20 + "@esbuild/linux-ppc64": 0.18.20 + "@esbuild/linux-riscv64": 0.18.20 + "@esbuild/linux-s390x": 0.18.20 + "@esbuild/linux-x64": 0.18.20 + "@esbuild/netbsd-x64": 0.18.20 + "@esbuild/openbsd-x64": 0.18.20 + "@esbuild/sunos-x64": 0.18.20 + "@esbuild/win32-arm64": 0.18.20 + "@esbuild/win32-ia32": 0.18.20 + "@esbuild/win32-x64": 0.18.20 + dependenciesMeta: + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 5d253614e50cdb6ec22095afd0c414f15688e7278a7eb4f3720a6dd1306b0909cf431e7b9437a90d065a31b1c57be60130f63fe3e8d0083b588571f31ee6ec7b + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.1.1 + resolution: "escalade@npm:3.1.1" + checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 + languageName: node + linkType: hard + +"escalade@npm:^3.2.0": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 47b029c83de01b0d17ad99ed766347b974b0d628e848de404018f3abee728e987da0d2d370ad4574aa3d5b5bfc368754fd085d69a30f8e75903486ec4b5b709e + languageName: node + linkType: hard + +"escape-goat@npm:^2.0.0": + version: 2.1.1 + resolution: "escape-goat@npm:2.1.1" + checksum: ce05c70c20dd7007b60d2d644b625da5412325fdb57acf671ba06cb2ab3cd6789e2087026921a05b665b0a03fadee2955e7fc0b9a67da15a6551a980b260eba7 + languageName: node + linkType: hard + +"escape-goat@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-goat@npm:4.0.0" + checksum: 7034e0025eec7b751074b837f10312c5b768493265bdad046347c0aadbc1e652776f7e5df94766473fecb5d3681169cc188fe9ccc1e22be53318c18be1671cc0 + languageName: node + linkType: hard + +"escape-html@npm:^1.0.3, escape-html@npm:~1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24 + languageName: node + linkType: hard + +"escape-string-regexp@npm:4.0.0, escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^1.0.5": + version: 1.0.5 + resolution: "escape-string-regexp@npm:1.0.5" + checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^5.0.0": + version: 5.0.0 + resolution: "escape-string-regexp@npm:5.0.0" + checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e + languageName: node + linkType: hard + +"escodegen@npm:^2.1.0": + version: 2.1.0 + resolution: "escodegen@npm:2.1.0" + dependencies: + esprima: ^4.0.1 + estraverse: ^5.2.0 + esutils: ^2.0.2 + source-map: ~0.6.1 + dependenciesMeta: + source-map: + optional: true + bin: + escodegen: bin/escodegen.js + esgenerate: bin/esgenerate.js + checksum: 096696407e161305cd05aebb95134ad176708bc5cb13d0dcc89a5fcbb959b8ed757e7f2591a5f8036f8f4952d4a724de0df14cd419e29212729fa6df5ce16bf6 + languageName: node + linkType: hard + +"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.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: eb2a7d46a1887e1b93788ee8f8eb81e0b6b2a6f5a66a62bc6f375b033fc4e7ca16448da99380be800042786e76cf5c0df9c87a51a2c9b960ed47acbd7c0b9381 + languageName: node + linkType: hard + +"eslint-scope@npm:5.1.1": + version: 5.1.1 + resolution: "eslint-scope@npm:5.1.1" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^4.1.1 + checksum: 47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb + languageName: node + linkType: hard + +"eslint-scope@npm:^7.2.2": + version: 7.2.2 + resolution: "eslint-scope@npm:7.2.2" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^5.2.0 + checksum: ec97dbf5fb04b94e8f4c5a91a7f0a6dd3c55e46bfc7bbcd0e3138c3a76977570e02ed89a1810c778dcd72072ff0e9621ba1379b4babe53921d71e2e4486fda3e + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": + version: 3.4.3 + resolution: "eslint-visitor-keys@npm:3.4.3" + checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60 + languageName: node + linkType: hard + +"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.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 + ajv: ^6.12.4 + chalk: ^4.0.0 + cross-spawn: ^7.0.2 + debug: ^4.3.2 + doctrine: ^3.0.0 + escape-string-regexp: ^4.0.0 + eslint-scope: ^7.2.2 + eslint-visitor-keys: ^3.4.3 + espree: ^9.6.1 + esquery: ^1.4.2 + esutils: ^2.0.2 + fast-deep-equal: ^3.1.3 + file-entry-cache: ^6.0.1 + find-up: ^5.0.0 + glob-parent: ^6.0.2 + globals: ^13.19.0 + graphemer: ^1.4.0 + ignore: ^5.2.0 + imurmurhash: ^0.1.4 + is-glob: ^4.0.0 + is-path-inside: ^3.0.3 + js-yaml: ^4.1.0 + json-stable-stringify-without-jsonify: ^1.0.1 + levn: ^0.4.1 + lodash.merge: ^4.6.2 + minimatch: ^3.1.2 + natural-compare: ^1.4.0 + optionator: ^0.9.3 + strip-ansi: ^6.0.1 + text-table: ^0.2.0 + bin: + eslint: bin/eslint.js + checksum: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 + languageName: node + linkType: hard + +"espree@npm:^9.6.0, espree@npm:^9.6.1": + version: 9.6.1 + resolution: "espree@npm:9.6.1" + dependencies: + acorn: ^8.9.0 + acorn-jsx: ^5.3.2 + eslint-visitor-keys: ^3.4.1 + checksum: eb8c149c7a2a77b3f33a5af80c10875c3abd65450f60b8af6db1bfcfa8f101e21c1e56a561c6dc13b848e18148d43469e7cd208506238554fb5395a9ea5a1ab9 + languageName: node + linkType: hard + +"esprima@npm:^4.0.0, esprima@npm:^4.0.1": + version: 4.0.1 + resolution: "esprima@npm:4.0.1" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: b45bc805a613dbea2835278c306b91aff6173c8d034223fa81498c77dcbce3b2931bf6006db816f62eacd9fd4ea975dfd85a5b7f3c6402cfd050d4ca3c13a628 + languageName: node + linkType: hard + +"esquery@npm:^1.4.2": + version: 1.5.0 + resolution: "esquery@npm:1.5.0" + dependencies: + estraverse: ^5.1.0 + checksum: aefb0d2596c230118656cd4ec7532d447333a410a48834d80ea648b1e7b5c9bc9ed8b5e33a89cb04e487b60d622f44cf5713bf4abed7c97343edefdc84a35900 + languageName: node + linkType: hard + +"esrecurse@npm:^4.3.0": + version: 4.3.0 + resolution: "esrecurse@npm:4.3.0" + dependencies: + estraverse: ^5.2.0 + checksum: ebc17b1a33c51cef46fdc28b958994b1dc43cd2e86237515cbc3b4e5d2be6a811b2315d0a1a4d9d340b6d2308b15322f5c8291059521cc5f4802f65e7ec32837 + languageName: node + linkType: hard + +"estraverse@npm:^4.1.1": + version: 4.3.0 + resolution: "estraverse@npm:4.3.0" + checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 + languageName: node + linkType: hard + +"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0": + version: 5.3.0 + resolution: "estraverse@npm:5.3.0" + checksum: 072780882dc8416ad144f8fe199628d2b3e7bbc9989d9ed43795d2c90309a2047e6bc5979d7e2322a341163d22cfad9e21f4110597fe487519697389497e4e2b + languageName: node + linkType: hard + +"estree-util-attach-comments@npm:^3.0.0": + version: 3.0.0 + resolution: "estree-util-attach-comments@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + checksum: 56254eaef39659e6351919ebc2ae53a37a09290a14571c19e373e9d5fad343a3403d9ad0c23ae465d6e7d08c3e572fd56fb8c793efe6434a261bf1489932dbd5 + languageName: node + linkType: hard + +"estree-util-build-jsx@npm:^3.0.0": + version: 3.0.1 + resolution: "estree-util-build-jsx@npm:3.0.1" + dependencies: + "@types/estree-jsx": ^1.0.0 + devlop: ^1.0.0 + estree-util-is-identifier-name: ^3.0.0 + estree-walker: ^3.0.0 + checksum: 185eff060eda2ba32cecd15904db4f5ba0681159fbdf54f0f6586cd9411e77e733861a833d0aee3415e1d1fd4b17edf08bc9e9872cee98e6ec7b0800e1a85064 + languageName: node + linkType: hard + +"estree-util-is-identifier-name@npm:^3.0.0": + version: 3.0.0 + resolution: "estree-util-is-identifier-name@npm:3.0.0" + checksum: ea3909f0188ea164af0aadeca87c087e3e5da78d76da5ae9c7954ff1340ea3e4679c4653bbf4299ffb70caa9b322218cc1128db2541f3d2976eb9704f9857787 + languageName: node + linkType: hard + +"estree-util-to-js@npm:^2.0.0": + version: 2.0.0 + resolution: "estree-util-to-js@npm:2.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + astring: ^1.8.0 + source-map: ^0.7.0 + checksum: 833edc94ab9978e0918f90261e0a3361bf4564fec4901f326d2237a9235d3f5fc6482da3be5acc545e702c8c7cb8bc5de5c7c71ba3b080eb1975bcfdf3923d79 + languageName: node + linkType: hard + +"estree-util-value-to-estree@npm:^3.0.1": + version: 3.0.1 + resolution: "estree-util-value-to-estree@npm:3.0.1" + dependencies: + "@types/estree": ^1.0.0 + is-plain-obj: ^4.0.0 + checksum: 7ab89084aa2c5677aeb0d7350ff21e71c9bbc424dc872a55bb4f25f63a7fd99fc7861626dd89b5544db3d3696212154bcf2b12b63ecd5a59dbfd07915c88aee4 + languageName: node + linkType: hard + +"estree-util-visit@npm:^2.0.0": + version: 2.0.0 + resolution: "estree-util-visit@npm:2.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/unist": ^3.0.0 + checksum: 6444b38f224322945a6d19ea81a8828a0eec64aefb2bf1ea791fe20df496f7b7c543408d637df899e6a8e318b638f66226f16378a33c4c2b192ba5c3f891121f + languageName: node + linkType: hard + +"estree-walker@npm:^2.0.2": + version: 2.0.2 + resolution: "estree-walker@npm:2.0.2" + checksum: 6151e6f9828abe2259e57f5fd3761335bb0d2ebd76dc1a01048ccee22fabcfef3c0859300f6d83ff0d1927849368775ec5a6d265dde2f6de5a1be1721cd94efc + languageName: node + linkType: hard + +"estree-walker@npm:^3.0.0": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": ^1.0.0 + checksum: a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af + languageName: node + linkType: hard + +"esutils@npm:^2.0.2": + version: 2.0.3 + resolution: "esutils@npm:2.0.3" + checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 + languageName: node + linkType: hard + +"eta@npm:^2.0.0, eta@npm:^2.2.0": + version: 2.2.0 + resolution: "eta@npm:2.2.0" + checksum: 6a09631481d4f26a9662a1eb736a65cc1cbc48e24935e6ff5d83a83b0cb509ea56d588d66d7c087d590601dc59bdabdac2356936b1b789d020eb0cf2d8304d54 + languageName: node + linkType: hard + +"etag@npm:^1.8.1, etag@npm:~1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff + languageName: node + linkType: hard + +"ethereum-cryptography@npm:0.1.3, ethereum-cryptography@npm:^0.1.3": + version: 0.1.3 + resolution: "ethereum-cryptography@npm:0.1.3" + dependencies: + "@types/pbkdf2": ^3.0.0 + "@types/secp256k1": ^4.0.1 + blakejs: ^1.1.0 + browserify-aes: ^1.2.0 + bs58check: ^2.1.2 + create-hash: ^1.2.0 + create-hmac: ^1.1.7 + hash.js: ^1.1.7 + keccak: ^3.0.0 + pbkdf2: ^3.0.17 + randombytes: ^2.1.0 + safe-buffer: ^5.1.2 + scrypt-js: ^3.0.0 + secp256k1: ^4.0.1 + setimmediate: ^1.0.5 + checksum: 54bae7a4a96bd81398cdc35c91cfcc74339f71a95ed1b5b694663782e69e8e3afd21357de3b8bac9ff4877fd6f043601e200a7ad9133d94be6fd7d898ee0a449 + languageName: node + linkType: hard + +"ethereum-cryptography@npm:^1.0.3": + version: 1.2.0 + resolution: "ethereum-cryptography@npm:1.2.0" + dependencies: + "@noble/hashes": 1.2.0 + "@noble/secp256k1": 1.7.1 + "@scure/bip32": 1.1.5 + "@scure/bip39": 1.1.1 + checksum: 97e8e8253cb9f5a9271bd0201c37609c451c890eb85883b9c564f14743c3d7c673287406c93bf5604307593ee298ad9a03983388b85c11ca61461b9fc1a4f2c7 + languageName: node + linkType: hard + +"ethereumjs-abi@npm:^0.6.8": + version: 0.6.8 + resolution: "ethereumjs-abi@npm:0.6.8" + dependencies: + bn.js: ^4.11.8 + ethereumjs-util: ^6.0.0 + checksum: cede2a8ae7c7e04eeaec079c2f925601a25b2ef75cf9230e7c5da63b4ea27883b35447365a47e35c1e831af520973a2252af89022c292c18a09a4607821a366b + languageName: node + linkType: hard + +"ethereumjs-util@npm:^6.0.0, ethereumjs-util@npm:^6.2.1": + version: 6.2.1 + resolution: "ethereumjs-util@npm:6.2.1" + dependencies: + "@types/bn.js": ^4.11.3 + bn.js: ^4.11.0 + create-hash: ^1.1.2 + elliptic: ^6.5.2 + ethereum-cryptography: ^0.1.3 + ethjs-util: 0.1.6 + rlp: ^2.2.3 + checksum: e3cb4a2c034a2529281fdfc21a2126fe032fdc3038863f5720352daa65ddcc50fc8c67dbedf381a882dc3802e05d979287126d7ecf781504bde1fd8218693bde + languageName: node + linkType: hard + +"ethers@npm:^6.7.1": + version: 6.9.0 + resolution: "ethers@npm:6.9.0" + dependencies: + "@adraffy/ens-normalize": 1.10.0 + "@noble/curves": 1.2.0 + "@noble/hashes": 1.3.2 + "@types/node": 18.15.13 + aes-js: 4.0.0-beta.5 + tslib: 2.4.0 + ws: 8.5.0 + checksum: e7b3b912b92b818fe65a192b32f4dd87ce0b71f4ffc194b4b3764b4b17d3b6ed953b667293e4c9276f785fa8c8659934c513843350317c61178af8e6165afbdd + languageName: node + linkType: hard + +"ethjs-util@npm:0.1.6, ethjs-util@npm:^0.1.6": + version: 0.1.6 + resolution: "ethjs-util@npm:0.1.6" + dependencies: + is-hex-prefixed: 1.0.0 + strip-hex-prefix: 1.0.0 + checksum: 1f42959e78ec6f49889c49c8a98639e06f52a15966387dd39faf2930db48663d026efb7db2702dcffe7f2a99c4a0144b7ce784efdbf733f4077aae95de76d65f + languageName: node + linkType: hard + +"eval@npm:^0.1.8": + version: 0.1.8 + resolution: "eval@npm:0.1.8" + dependencies: + "@types/node": "*" + require-like: ">= 0.1.1" + checksum: d005567f394cfbe60948e34982e4637d2665030f9aa7dcac581ea6f9ec6eceb87133ed3dc0ae21764aa362485c242a731dbb6371f1f1a86807c58676431e9d1a + languageName: node + linkType: hard + +"event-target-shim@npm:^5.0.0": + version: 5.0.1 + resolution: "event-target-shim@npm:5.0.1" + checksum: 1ffe3bb22a6d51bdeb6bf6f7cf97d2ff4a74b017ad12284cc9e6a279e727dc30a5de6bb613e5596ff4dc3e517841339ad09a7eec44266eccb1aa201a30448166 + languageName: node + linkType: hard + +"eventemitter3@npm:^4.0.0": + version: 4.0.7 + resolution: "eventemitter3@npm:4.0.7" + checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 + languageName: node + linkType: hard + +"events@npm:^3.2.0, events@npm:^3.3.0": + version: 3.3.0 + resolution: "events@npm:3.3.0" + checksum: f6f487ad2198aa41d878fa31452f1a3c00958f46e9019286ff4787c84aac329332ab45c9cdc8c445928fc6d7ded294b9e005a7fce9426488518017831b272780 + languageName: node + linkType: hard + +"evp_bytestokey@npm:^1.0.3": + version: 1.0.3 + resolution: "evp_bytestokey@npm:1.0.3" + dependencies: + md5.js: ^1.3.4 + node-gyp: latest + safe-buffer: ^5.1.1 + checksum: ad4e1577f1a6b721c7800dcc7c733fe01f6c310732bb5bf2240245c2a5b45a38518b91d8be2c610611623160b9d1c0e91f1ce96d639f8b53e8894625cf20fa45 + languageName: node + linkType: hard + +"execa@npm:^5.0.0, execa@npm:^5.1.1": + version: 5.1.1 + resolution: "execa@npm:5.1.1" + dependencies: + cross-spawn: ^7.0.3 + get-stream: ^6.0.0 + human-signals: ^2.1.0 + is-stream: ^2.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^4.0.1 + onetime: ^5.1.2 + signal-exit: ^3.0.3 + strip-final-newline: ^2.0.0 + checksum: fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343 + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 3d21519a4f8207c99f7457287291316306255a328770d320b401114ec8481986e4e467e854cb9914dd965e0a1ca810a23ccb559c642c88f4c7f55c55778a9b48 + languageName: node + linkType: hard + +"express@npm:^4.17.3": + version: 4.18.2 + resolution: "express@npm:4.18.2" + dependencies: + accepts: ~1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: ~1.0.4 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + etag: ~1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: ~1.1.2 + on-finished: 2.4.1 + parseurl: ~1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: ~2.0.7 + qs: 6.11.0 + range-parser: ~1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: ~1.6.18 + utils-merge: 1.0.1 + vary: ~1.1.2 + checksum: 3c4b9b076879442f6b968fe53d85d9f1eeacbb4f4c41e5f16cc36d77ce39a2b0d81b3f250514982110d815b2f7173f5561367f9110fcc541f9371948e8c8b037 + languageName: node + linkType: hard + +"extend-shallow@npm:^2.0.1": + version: 2.0.1 + resolution: "extend-shallow@npm:2.0.1" + dependencies: + is-extendable: ^0.1.0 + checksum: 8fb58d9d7a511f4baf78d383e637bd7d2e80843bd9cd0853649108ea835208fb614da502a553acc30208e1325240bb7cc4a68473021612496bb89725483656d8 + languageName: node + linkType: hard + +"extend@npm:^3.0.0": + version: 3.0.2 + resolution: "extend@npm:3.0.2" + checksum: a50a8309ca65ea5d426382ff09f33586527882cf532931cb08ca786ea3146c0553310bda688710ff61d7668eba9f96b923fe1420cdf56a2c3eaf30fcab87b515 + languageName: node + linkType: hard + +"extract-zip@npm:2.0.1": + version: 2.0.1 + resolution: "extract-zip@npm:2.0.1" + dependencies: + "@types/yauzl": ^2.9.1 + debug: ^4.1.1 + get-stream: ^5.1.0 + yauzl: ^2.10.0 + dependenciesMeta: + "@types/yauzl": + optional: true + bin: + extract-zip: cli.js + checksum: 8cbda9debdd6d6980819cc69734d874ddd71051c9fe5bde1ef307ebcedfe949ba57b004894b585f758b7c9eeeea0e3d87f2dda89b7d25320459c2c9643ebb635 + languageName: node + linkType: hard + +"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": + version: 3.1.3 + resolution: "fast-deep-equal@npm:3.1.3" + checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d + languageName: node + linkType: hard + +"fast-diff@npm:^1.1.2": + version: 1.3.0 + resolution: "fast-diff@npm:1.3.0" + checksum: d22d371b994fdc8cce9ff510d7b8dc4da70ac327bcba20df607dd5b9cae9f908f4d1028f5fe467650f058d1e7270235ae0b8230809a262b4df587a3b3aa216c3 + languageName: node + linkType: hard + +"fast-equals@npm:^5.0.1": + version: 5.0.1 + resolution: "fast-equals@npm:5.0.1" + checksum: fbb3b6a74f3a0fa930afac151ff7d01639159b4fddd2678b5d50708e0ba38e9ec14602222d10dadb8398187342692c04fbef5a62b1cfcc7942fe03e754e064bc + languageName: node + linkType: hard + +"fast-fifo@npm:^1.1.0, fast-fifo@npm:^1.2.0": + version: 1.3.2 + resolution: "fast-fifo@npm:1.3.2" + checksum: 6bfcba3e4df5af7be3332703b69a7898a8ed7020837ec4395bb341bd96cc3a6d86c3f6071dd98da289618cf2234c70d84b2a6f09a33dd6f988b1ff60d8e54275 + languageName: node + linkType: hard + +"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.2": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" + dependencies: + "@nodelib/fs.stat": ^2.0.2 + "@nodelib/fs.walk": ^1.2.3 + glob-parent: ^5.1.2 + merge2: ^1.3.0 + micromatch: ^4.0.4 + checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1 + languageName: node + linkType: hard + +"fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": + version: 2.1.0 + resolution: "fast-json-stable-stringify@npm:2.1.0" + checksum: b191531e36c607977e5b1c47811158733c34ccb3bfde92c44798929e9b4154884378536d26ad90dfecd32e1ffc09c545d23535ad91b3161a27ddbb8ebe0cbecb + languageName: node + linkType: hard + +"fast-levenshtein@npm:^2.0.6": + version: 2.0.6 + resolution: "fast-levenshtein@npm:2.0.6" + checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c + languageName: node + linkType: hard + +"fast-url-parser@npm:1.1.3": + version: 1.1.3 + resolution: "fast-url-parser@npm:1.1.3" + dependencies: + punycode: ^1.3.2 + checksum: 5043d0c4a8d775ff58504d56c096563c11b113e4cb8a2668c6f824a1cd4fb3812e2fdf76537eb24a7ce4ae7def6bd9747da630c617cf2a4b6ce0c42514e4f21c + languageName: node + linkType: hard + +"fastest-levenshtein@npm:^1.0.12": + version: 1.0.16 + resolution: "fastest-levenshtein@npm:1.0.16" + checksum: a78d44285c9e2ae2c25f3ef0f8a73f332c1247b7ea7fb4a191e6bb51aa6ee1ef0dfb3ed113616dcdc7023e18e35a8db41f61c8d88988e877cf510df8edafbc71 + languageName: node + linkType: hard + +"fastq@npm:^1.6.0": + version: 1.15.0 + resolution: "fastq@npm:1.15.0" + dependencies: + reusify: ^1.0.4 + checksum: 0170e6bfcd5d57a70412440b8ef600da6de3b2a6c5966aeaf0a852d542daff506a0ee92d6de7679d1de82e644bce69d7a574a6c93f0b03964b5337eed75ada1a + languageName: node + linkType: hard + +"fault@npm:^2.0.0": + version: 2.0.1 + resolution: "fault@npm:2.0.1" + dependencies: + format: ^0.2.0 + checksum: c9b30f47d95769177130a9409976a899ed31eb598450fbad5b0d39f2f5f56d5f4a9ff9257e0bee8407cb0fc3ce37165657888c6aa6d78472e403893104329b72 + languageName: node + linkType: hard + +"faye-websocket@npm:^0.11.3": + version: 0.11.4 + resolution: "faye-websocket@npm:0.11.4" + dependencies: + websocket-driver: ">=0.5.1" + checksum: d49a62caf027f871149fc2b3f3c7104dc6d62744277eb6f9f36e2d5714e847d846b9f7f0d0b7169b25a012e24a594cde11a93034b30732e4c683f20b8a5019fa + languageName: node + linkType: hard + +"fd-slicer@npm:~1.1.0": + version: 1.1.0 + resolution: "fd-slicer@npm:1.1.0" + dependencies: + pend: ~1.2.0 + checksum: c8585fd5713f4476eb8261150900d2cb7f6ff2d87f8feb306ccc8a1122efd152f1783bdb2b8dc891395744583436bfd8081d8e63ece0ec8687eeefea394d4ff2 + languageName: node + linkType: hard + +"feed@npm:^4.2.2": + version: 4.2.2 + resolution: "feed@npm:4.2.2" + dependencies: + xml-js: ^1.6.11 + checksum: 2e6992a675a049511eef7bda8ca6c08cb9540cd10e8b275ec4c95d166228ec445a335fa8de990358759f248a92861e51decdcd32bf1c54737d5b7aed7c7ffe97 + languageName: node + linkType: hard + +"fflate@npm:^0.8.0": + version: 0.8.1 + resolution: "fflate@npm:0.8.1" + checksum: 7207e2d333243724485d2488095256b776184bd4545aa9967b655feaee5dc18e9525ed9b6d75f94cfd71d98fb285336f4902641683472f1d0c19a99137084cec + languageName: node + linkType: hard + +"file-entry-cache@npm:^6.0.1": + version: 6.0.1 + resolution: "file-entry-cache@npm:6.0.1" + dependencies: + flat-cache: ^3.0.4 + checksum: f49701feaa6314c8127c3c2f6173cfefff17612f5ed2daaafc6da13b5c91fd43e3b2a58fd0d63f9f94478a501b167615931e7200e31485e320f74a33885a9c74 + languageName: node + linkType: hard + +"file-entry-cache@npm:^8.0.0": + version: 8.0.0 + resolution: "file-entry-cache@npm:8.0.0" + dependencies: + flat-cache: ^4.0.0 + checksum: f67802d3334809048c69b3d458f672e1b6d26daefda701761c81f203b80149c35dea04d78ea4238969dd617678e530876722a0634c43031a0957f10cc3ed190f + languageName: node + linkType: hard + +"file-loader@npm:^6.2.0": + version: 6.2.0 + resolution: "file-loader@npm:6.2.0" + dependencies: + loader-utils: ^2.0.0 + schema-utils: ^3.0.0 + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + checksum: faf43eecf233f4897b0150aaa874eeeac214e4f9de49738a9e0ef734a30b5260059e85b7edadf852b98e415f875bd5f12587768a93fd52aaf2e479ecf95fab20 + languageName: node + linkType: hard + +"filesize@npm:^8.0.6": + version: 8.0.7 + resolution: "filesize@npm:8.0.7" + checksum: 8603d27c5287b984cb100733640645e078f5f5ad65c6d913173e01fb99e09b0747828498fd86647685ccecb69be31f3587b9739ab1e50732116b2374aff4cbf9 + languageName: node + linkType: hard + +"fill-range@npm:^7.0.1": + version: 7.0.1 + resolution: "fill-range@npm:7.0.1" + dependencies: + to-regex-range: ^5.0.1 + checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 + languageName: node + linkType: hard + +"finalhandler@npm:1.2.0": + version: 1.2.0 + resolution: "finalhandler@npm:1.2.0" + dependencies: + debug: 2.6.9 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + on-finished: 2.4.1 + parseurl: ~1.3.3 + statuses: 2.0.1 + unpipe: ~1.0.0 + checksum: 92effbfd32e22a7dff2994acedbd9bcc3aa646a3e919ea6a53238090e87097f8ef07cced90aa2cc421abdf993aefbdd5b00104d55c7c5479a8d00ed105b45716 + languageName: node + linkType: hard + +"find-cache-dir@npm:^3.3.1": + version: 3.3.2 + resolution: "find-cache-dir@npm:3.3.2" + dependencies: + commondir: ^1.0.1 + make-dir: ^3.0.2 + pkg-dir: ^4.1.0 + checksum: 1e61c2e64f5c0b1c535bd85939ae73b0e5773142713273818cc0b393ee3555fb0fd44e1a5b161b8b6c3e03e98c2fcc9c227d784850a13a90a8ab576869576817 + languageName: node + linkType: hard + +"find-cache-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "find-cache-dir@npm:4.0.0" + dependencies: + common-path-prefix: ^3.0.0 + pkg-dir: ^7.0.0 + checksum: 52a456a80deeb27daa3af6e06059b63bdb9cc4af4d845fc6d6229887e505ba913cd56000349caa60bc3aa59dacdb5b4c37903d4ba34c75102d83cab330b70d2f + languageName: node + linkType: hard + +"find-replace@npm:^3.0.0": + version: 3.0.0 + resolution: "find-replace@npm:3.0.0" + dependencies: + array-back: ^3.0.1 + checksum: 6b04bcfd79027f5b84aa1dfe100e3295da989bdac4b4de6b277f4d063e78f5c9e92ebc8a1fec6dd3b448c924ba404ee051cc759e14a3ee3e825fa1361025df08 + languageName: node + linkType: hard + +"find-up-simple@npm:^1.0.0": + version: 1.0.0 + resolution: "find-up-simple@npm:1.0.0" + checksum: 91c3d51c1111b5eb4e6e6d71d21438f6571a37a69dc288d4222b98996756e2f472fa5393a4dddb5e1a84929405d87e86f4bdce798ba84ee513b79854960ec140 + languageName: node + linkType: hard + +"find-up@npm:5.0.0, find-up@npm:^5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: ^6.0.0 + path-exists: ^4.0.0 + checksum: 07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095 + languageName: node + linkType: hard + +"find-up@npm:^2.1.0": + version: 2.1.0 + resolution: "find-up@npm:2.1.0" + dependencies: + locate-path: ^2.0.0 + checksum: 43284fe4da09f89011f08e3c32cd38401e786b19226ea440b75386c1b12a4cb738c94969808d53a84f564ede22f732c8409e3cfc3f7fb5b5c32378ad0bbf28bd + languageName: node + linkType: hard + +"find-up@npm:^3.0.0": + version: 3.0.0 + resolution: "find-up@npm:3.0.0" + dependencies: + locate-path: ^3.0.0 + checksum: 38eba3fe7a66e4bc7f0f5a1366dc25508b7cfc349f852640e3678d26ad9a6d7e2c43eff0a472287de4a9753ef58f066a0ea892a256fa3636ad51b3fe1e17fae9 + languageName: node + linkType: hard + +"find-up@npm:^4.0.0": + version: 4.1.0 + resolution: "find-up@npm:4.1.0" + dependencies: + locate-path: ^5.0.0 + path-exists: ^4.0.0 + checksum: 4c172680e8f8c1f78839486e14a43ef82e9decd0e74145f40707cc42e7420506d5ec92d9a11c22bd2c48fb0c384ea05dd30e10dd152fefeec6f2f75282a8b844 + languageName: node + linkType: hard + +"find-up@npm:^6.3.0": + version: 6.3.0 + resolution: "find-up@npm:6.3.0" + dependencies: + locate-path: ^7.1.0 + path-exists: ^5.0.0 + checksum: 9a21b7f9244a420e54c6df95b4f6fc3941efd3c3e5476f8274eb452f6a85706e7a6a90de71353ee4f091fcb4593271a6f92810a324ec542650398f928783c280 + languageName: node + linkType: hard + +"flat-cache@npm:^3.0.4": + version: 3.2.0 + resolution: "flat-cache@npm:3.2.0" + dependencies: + flatted: ^3.2.9 + keyv: ^4.5.3 + rimraf: ^3.0.2 + checksum: e7e0f59801e288b54bee5cb9681e9ee21ee28ef309f886b312c9d08415b79fc0f24ac842f84356ce80f47d6a53de62197ce0e6e148dc42d5db005992e2a756ec + languageName: node + linkType: hard + +"flat-cache@npm:^4.0.0": + version: 4.0.0 + resolution: "flat-cache@npm:4.0.0" + dependencies: + flatted: ^3.2.9 + keyv: ^4.5.4 + rimraf: ^5.0.5 + checksum: 744d5f111aeecdfb963faab7089230c737a90c325137251b4fe144fd76932e19738a861e356c5ee828bb310592b42a1da667912d74d0403f1f4ef75be8bfdbac + languageName: node + linkType: hard + +"flat@npm:^5.0.2": + version: 5.0.2 + resolution: "flat@npm:5.0.2" + bin: + flat: cli.js + checksum: 12a1536ac746db74881316a181499a78ef953632ddd28050b7a3a43c62ef5462e3357c8c29d76072bb635f147f7a9a1f0c02efef6b4be28f8db62ceb3d5c7f5d + languageName: node + linkType: hard + +"flatted@npm:^3.2.9": + version: 3.2.9 + resolution: "flatted@npm:3.2.9" + checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026 + languageName: node + linkType: hard + +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.7, follow-redirects@npm:^1.15.0": + version: 1.15.3 + resolution: "follow-redirects@npm:1.15.3" + peerDependenciesMeta: + debug: + optional: true + checksum: 584da22ec5420c837bd096559ebfb8fe69d82512d5585004e36a3b4a6ef6d5905780e0c74508c7b72f907d1fa2b7bd339e613859e9c304d0dc96af2027fd0231 + languageName: node + linkType: hard + +"for-each@npm:^0.3.3": + version: 0.3.3 + resolution: "for-each@npm:0.3.3" + dependencies: + is-callable: ^1.1.3 + checksum: 6c48ff2bc63362319c65e2edca4a8e1e3483a2fabc72fbe7feaf8c73db94fc7861bd53bc02c8a66a0c1dd709da6b04eec42e0abdd6b40ce47305ae92a25e5d28 + languageName: node + linkType: hard + +"foreach@npm:~2.0.1": + version: 2.0.6 + resolution: "foreach@npm:2.0.6" + checksum: f7b68494545ee41cbd0b0425ebf5386c265dc38ef2a9b0d5cd91a1b82172e939b4cf9387f8e0ebf6db4e368fc79ed323f2198424d5c774515ac3ed9b08901c0e + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.1.1 + resolution: "foreground-child@npm:3.1.1" + dependencies: + cross-spawn: ^7.0.0 + signal-exit: ^4.0.1 + checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 + languageName: node + linkType: hard + +"fork-ts-checker-webpack-plugin@npm:^6.5.0": + version: 6.5.3 + resolution: "fork-ts-checker-webpack-plugin@npm:6.5.3" + dependencies: + "@babel/code-frame": ^7.8.3 + "@types/json-schema": ^7.0.5 + chalk: ^4.1.0 + chokidar: ^3.4.2 + cosmiconfig: ^6.0.0 + deepmerge: ^4.2.2 + fs-extra: ^9.0.0 + glob: ^7.1.6 + memfs: ^3.1.2 + minimatch: ^3.0.4 + schema-utils: 2.7.0 + semver: ^7.3.2 + tapable: ^1.0.0 + peerDependencies: + eslint: ">= 6" + typescript: ">= 2.7" + vue-template-compiler: "*" + webpack: ">= 4" + peerDependenciesMeta: + eslint: + optional: true + vue-template-compiler: + optional: true + checksum: 9732a49bfeed8fc23e6e8a59795fa7c238edeba91040a9b520db54b4d316dda27f9f1893d360e296fd0ad8930627d364417d28a8c7007fba60cc730ebfce4956 + languageName: node + linkType: hard + +"form-data-encoder@npm:^2.1.2": + version: 2.1.4 + resolution: "form-data-encoder@npm:2.1.4" + checksum: e0b3e5950fb69b3f32c273944620f9861f1933df9d3e42066e038e26dfb343d0f4465de9f27e0ead1a09d9df20bc2eed06a63c2ca2f8f00949e7202bae9e29dd + languageName: node + linkType: hard + +"form-data@npm:^4.0.0": + version: 4.0.0 + resolution: "form-data@npm:4.0.0" + dependencies: + asynckit: ^0.4.0 + combined-stream: ^1.0.8 + mime-types: ^2.1.12 + checksum: 01135bf8675f9d5c61ff18e2e2932f719ca4de964e3be90ef4c36aacfc7b9cb2fceb5eca0b7e0190e3383fe51c5b37f4cb80b62ca06a99aaabfcfd6ac7c9328c + languageName: node + linkType: hard + +"format@npm:^0.2.0": + version: 0.2.2 + resolution: "format@npm:0.2.2" + checksum: 646a60e1336250d802509cf24fb801e43bd4a70a07510c816fa133aa42cdbc9c21e66e9cc0801bb183c5b031c9d68be62e7fbb6877756e52357850f92aa28799 + languageName: node + linkType: hard + +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: fd27e2394d8887ebd16a66ffc889dc983fbbd797d5d3f01087c020283c0f019a7d05ee85669383d8e0d216b116d720fc0cef2f6e9b7eb9f4c90c6e0bc7fd28e6 + languageName: node + linkType: hard + +"fp-ts@npm:1.19.3": + version: 1.19.3 + resolution: "fp-ts@npm:1.19.3" + checksum: eb0d4766ad561e9c5c01bfdd3d0ae589af135556921c733d26cf5289aad9f400110defdd93e6ac1d71f626697bb44d9d95ed2879c53dfd868f7cac3cf5c5553c + languageName: node + linkType: hard + +"fp-ts@npm:^1.0.0": + version: 1.19.5 + resolution: "fp-ts@npm:1.19.5" + checksum: 67d2d9c3855d211ca2592b1ef805f98b618157e7681791a776d9d0f7f3e52fcca2122ebf5bc215908c9099fad69756d40e37210cf46cb4075dae1b61efe69e40 + languageName: node + linkType: hard + +"fraction.js@npm:^4.3.6, fraction.js@npm:^4.3.7": + version: 4.3.7 + resolution: "fraction.js@npm:4.3.7" + checksum: e1553ae3f08e3ba0e8c06e43a3ab20b319966dfb7ddb96fd9b5d0ee11a66571af7f993229c88ebbb0d4a816eb813a24ed48207b140d442a8f76f33763b8d1f3f + languageName: node + linkType: hard + +"fresh@npm:0.5.2, fresh@npm:~0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 13ea8b08f91e669a64e3ba3a20eb79d7ca5379a81f1ff7f4310d54e2320645503cc0c78daedc93dfb6191287295f6479544a649c64d8e41a1c0fb0c221552346 + languageName: node + linkType: hard + +"fs-extra@npm:^10.0.0, fs-extra@npm:^10.1.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: dc94ab37096f813cc3ca12f0f1b5ad6744dfed9ed21e953d72530d103cea193c2f81584a39e9dee1bea36de5ee66805678c0dddc048e8af1427ac19c00fffc50 + languageName: node + linkType: hard + +"fs-extra@npm:^11.1.1, fs-extra@npm:^11.2.0": + version: 11.2.0 + resolution: "fs-extra@npm:11.2.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: b12e42fa40ba47104202f57b8480dd098aa931c2724565e5e70779ab87605665594e76ee5fb00545f772ab9ace167fe06d2ab009c416dc8c842c5ae6df7aa7e8 + languageName: node + linkType: hard + +"fs-extra@npm:^7.0.1": + version: 7.0.1 + resolution: "fs-extra@npm:7.0.1" + dependencies: + graceful-fs: ^4.1.2 + jsonfile: ^4.0.0 + universalify: ^0.1.0 + checksum: 141b9dccb23b66a66cefdd81f4cda959ff89282b1d721b98cea19ba08db3dcbe6f862f28841f3cf24bb299e0b7e6c42303908f65093cb7e201708e86ea5a8dcf + languageName: node + linkType: hard + +"fs-extra@npm:^8.1.0": + version: 8.1.0 + resolution: "fs-extra@npm:8.1.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^4.0.0 + universalify: ^0.1.0 + checksum: bf44f0e6cea59d5ce071bba4c43ca76d216f89e402dc6285c128abc0902e9b8525135aa808adad72c9d5d218e9f4bcc63962815529ff2f684ad532172a284880 + languageName: node + linkType: hard + +"fs-extra@npm:^9.0.0": + version: 9.1.0 + resolution: "fs-extra@npm:9.1.0" + dependencies: + at-least-node: ^1.0.0 + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: ba71ba32e0faa74ab931b7a0031d1523c66a73e225de7426e275e238e312d07313d2da2d33e34a52aa406c8763ade5712eb3ec9ba4d9edce652bcacdc29e6b20 + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: ^3.0.0 + checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: ^7.0.3 + checksum: 8722a41109130851d979222d3ec88aabaceeaaf8f57b2a8f744ef8bd2d1ce95453b04a61daa0078822bc5cd21e008814f06fe6586f56fef511e71b8d2394d802 + languageName: node + linkType: hard + +"fs-monkey@npm:^1.0.4": + version: 1.0.5 + resolution: "fs-monkey@npm:1.0.5" + checksum: 424b67f65b37fe66117ae2bb061f790fe6d4b609e1d160487c74b3d69fbf42f262c665ccfba32e8b5f113f96f92e9a58fcdebe42d5f6649bdfc72918093a3119 + languageName: node + linkType: hard + +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 + languageName: node + linkType: hard + +"fsevents@npm:2.3.2": + version: 2.3.2 + resolution: "fsevents@npm:2.3.2" + dependencies: + node-gyp: latest + checksum: 97ade64e75091afee5265e6956cb72ba34db7819b4c3e94c431d4be2b19b8bb7a2d4116da417950c3425f17c8fe693d25e20212cac583ac1521ad066b77ae31f + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@2.3.2#~builtin": + version: 2.3.2 + resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin::version=2.3.2&hash=df0bf1" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@~2.3.2#~builtin, fsevents@patch:fsevents@~2.3.3#~builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1 + languageName: node + linkType: hard + +"fwd-stream@npm:^1.0.4": + version: 1.0.4 + resolution: "fwd-stream@npm:1.0.4" + dependencies: + readable-stream: ~1.0.26-4 + checksum: db4dcf68f214b3fabd6cd9658630dfd1d7ed8d43f7f45408027a90220cd75276e782d1e958821775d7a3a4a83034778e75a097bdc7002c758e8896f76213c65d + languageName: node + linkType: hard + +"gensequence@npm:^6.0.0": + version: 6.0.0 + resolution: "gensequence@npm:6.0.0" + checksum: 7c23404b227647cb033a2c6cf5a5266442409e9dcc6bc140565d28de64adfa03dc474119ae14d776dc177fe63d605d2f4b228fa3bf926145dddd68c8df95d029 + languageName: node + linkType: hard + +"gensync@npm:^1.0.0-beta.1, gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: a7437e58c6be12aa6c90f7730eac7fa9833dc78872b4ad2963d2031b00a3367a93f98aec75f9aaac7220848e4026d67a8655e870b24f20a543d103c0d65952ec + languageName: node + linkType: hard + +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: b9769a836d2a98c3ee734a88ba712e62703f1df31b94b784762c433c27a386dd6029ff55c2a920c392e33657d80191edbf18c61487e198844844516f843496b9 + languageName: node + linkType: hard + +"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": + version: 1.2.2 + resolution: "get-intrinsic@npm:1.2.2" + dependencies: + function-bind: ^1.1.2 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + hasown: ^2.0.0 + checksum: 447ff0724df26829908dc033b62732359596fcf66027bc131ab37984afb33842d9cd458fd6cecadfe7eac22fd8a54b349799ed334cf2726025c921c7250e7417 + languageName: node + linkType: hard + +"get-own-enumerable-property-symbols@npm:^3.0.0": + version: 3.0.2 + resolution: "get-own-enumerable-property-symbols@npm:3.0.2" + checksum: 8f0331f14159f939830884799f937343c8c0a2c330506094bc12cbee3665d88337fe97a4ea35c002cc2bdba0f5d9975ad7ec3abb925015cdf2a93e76d4759ede + languageName: node + linkType: hard + +"get-stdin@npm:^8.0.0": + version: 8.0.0 + resolution: "get-stdin@npm:8.0.0" + checksum: 40128b6cd25781ddbd233344f1a1e4006d4284906191ed0a7d55ec2c1a3e44d650f280b2c9eeab79c03ac3037da80257476c0e4e5af38ddfb902d6ff06282d77 + languageName: node + linkType: hard + +"get-stdin@npm:^9.0.0": + version: 9.0.0 + resolution: "get-stdin@npm:9.0.0" + checksum: 5972bc34d05932b45512c8e2d67b040f1c1ca8afb95c56cbc480985f2d761b7e37fe90dc8abd22527f062cc5639a6930ff346e9952ae4c11a2d4275869459594 + languageName: node + linkType: hard + +"get-stream@npm:^4.1.0": + version: 4.1.0 + resolution: "get-stream@npm:4.1.0" + dependencies: + pump: ^3.0.0 + checksum: 443e1914170c15bd52ff8ea6eff6dfc6d712b031303e36302d2778e3de2506af9ee964d6124010f7818736dcfde05c04ba7ca6cc26883106e084357a17ae7d73 + languageName: node + linkType: hard + +"get-stream@npm:^5.1.0": + version: 5.2.0 + resolution: "get-stream@npm:5.2.0" + dependencies: + pump: ^3.0.0 + checksum: 8bc1a23174a06b2b4ce600df38d6c98d2ef6d84e020c1ddad632ad75bac4e092eeb40e4c09e0761c35fc2dbc5e7fff5dab5e763a383582c4a167dd69a905bd12 + languageName: node + linkType: hard + +"get-stream@npm:^6.0.0, get-stream@npm:^6.0.1": + version: 6.0.1 + resolution: "get-stream@npm:6.0.1" + checksum: e04ecece32c92eebf5b8c940f51468cd53554dcbb0ea725b2748be583c9523d00128137966afce410b9b051eb2ef16d657cd2b120ca8edafcf5a65e81af63cad + languageName: node + linkType: hard + +"get-tsconfig@npm:^4.7.2": + version: 4.7.2 + resolution: "get-tsconfig@npm:4.7.2" + dependencies: + resolve-pkg-maps: ^1.0.0 + checksum: 172358903250eff0103943f816e8a4e51d29b8e5449058bdf7266714a908a48239f6884308bd3a6ff28b09f692b9533dbebfd183ab63e4e14f073cda91f1bca9 + languageName: node + linkType: hard + +"get-uri@npm:^6.0.1": + version: 6.0.2 + resolution: "get-uri@npm:6.0.2" + dependencies: + basic-ftp: ^5.0.2 + data-uri-to-buffer: ^6.0.0 + debug: ^4.3.4 + fs-extra: ^8.1.0 + checksum: 762de3b0e3d4e7afc966e4ce93be587d70c270590da9b4c8fbff888362656c055838d926903d1774cbfeed4d392b4d6def4b2c06d48c050580070426a3a8629b + languageName: node + linkType: hard + +"github-slugger@npm:^1.4.0, github-slugger@npm:^1.5.0": + version: 1.5.0 + resolution: "github-slugger@npm:1.5.0" + checksum: c70988224578b3bdaa25df65973ffc8c24594a77a28550c3636e495e49d17aef5cdb04c04fa3f1744babef98c61eecc6a43299a13ea7f3cc33d680bf9053ffbe + languageName: node + linkType: hard + +"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": + version: 5.1.2 + resolution: "glob-parent@npm:5.1.2" + dependencies: + is-glob: ^4.0.1 + checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e + languageName: node + linkType: hard + +"glob-parent@npm:^6.0.1, glob-parent@npm:^6.0.2": + version: 6.0.2 + resolution: "glob-parent@npm:6.0.2" + dependencies: + is-glob: ^4.0.3 + checksum: c13ee97978bef4f55106b71e66428eb1512e71a7466ba49025fc2aec59a5bfb0954d5abd58fc5ee6c9b076eef4e1f6d3375c2e964b88466ca390da4419a786a8 + languageName: node + linkType: hard + +"glob-to-regexp@npm:^0.4.1": + version: 0.4.1 + resolution: "glob-to-regexp@npm:0.4.1" + checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167 + languageName: node + linkType: hard + +"glob@npm:7.2.0": + version: 7.2.0 + resolution: "glob@npm:7.2.0" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^3.0.4 + once: ^1.3.0 + path-is-absolute: ^1.0.0 + checksum: 78a8ea942331f08ed2e055cb5b9e40fe6f46f579d7fd3d694f3412fe5db23223d29b7fee1575440202e9a7ff9a72ab106a39fee39934c7bedafe5e5f8ae20134 + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.3.5 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 + bin: + glob: dist/esm/bin.mjs + checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + languageName: node + linkType: hard + +"glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.6": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^3.1.1 + once: ^1.3.0 + path-is-absolute: ^1.0.0 + checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 + languageName: node + linkType: hard + +"global-directory@npm:^4.0.1": + version: 4.0.1 + resolution: "global-directory@npm:4.0.1" + dependencies: + ini: 4.1.1 + checksum: 5b4df24438a4e5f21e43fbdd9e54f5e12bb48dce01a0a83b415d8052ce91be2d3a97e0c8f98a535e69649b2190036155e9f0f7d3c62f9318f31bdc3fd4f235f5 + languageName: node + linkType: hard + +"global-dirs@npm:^3.0.0": + version: 3.0.1 + resolution: "global-dirs@npm:3.0.1" + dependencies: + ini: 2.0.0 + checksum: 70147b80261601fd40ac02a104581432325c1c47329706acd773f3a6ce99bb36d1d996038c85ccacd482ad22258ec233c586b6a91535b1a116b89663d49d6438 + languageName: node + linkType: hard + +"global-modules@npm:^2.0.0": + version: 2.0.0 + resolution: "global-modules@npm:2.0.0" + dependencies: + global-prefix: ^3.0.0 + checksum: d6197f25856c878c2fb5f038899f2dca7cbb2f7b7cf8999660c0104972d5cfa5c68b5a0a77fa8206bb536c3903a4615665acb9709b4d80846e1bb47eaef65430 + languageName: node + linkType: hard + +"global-prefix@npm:^3.0.0": + version: 3.0.0 + resolution: "global-prefix@npm:3.0.0" + dependencies: + ini: ^1.3.5 + kind-of: ^6.0.2 + which: ^1.3.1 + checksum: 8a82fc1d6f22c45484a4e34656cc91bf021a03e03213b0035098d605bfc612d7141f1e14a21097e8a0413b4884afd5b260df0b6a25605ce9d722e11f1df2881d + languageName: node + linkType: hard + +"globals@npm:^11.1.0": + version: 11.12.0 + resolution: "globals@npm:11.12.0" + checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e + languageName: node + linkType: hard + +"globals@npm:^13.19.0": + version: 13.24.0 + resolution: "globals@npm:13.24.0" + dependencies: + type-fest: ^0.20.2 + checksum: 56066ef058f6867c04ff203b8a44c15b038346a62efbc3060052a1016be9f56f4cf0b2cd45b74b22b81e521a889fc7786c73691b0549c2f3a6e825b3d394f43c + languageName: node + linkType: hard + +"globby@npm:^11.0.1, globby@npm:^11.0.4, globby@npm:^11.1.0": + version: 11.1.0 + resolution: "globby@npm:11.1.0" + dependencies: + array-union: ^2.1.0 + dir-glob: ^3.0.1 + fast-glob: ^3.2.9 + ignore: ^5.2.0 + merge2: ^1.4.1 + slash: ^3.0.0 + checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 + languageName: node + linkType: hard + +"globby@npm:^13.1.1": + version: 13.2.2 + resolution: "globby@npm:13.2.2" + dependencies: + dir-glob: ^3.0.1 + fast-glob: ^3.3.0 + ignore: ^5.2.4 + merge2: ^1.4.1 + slash: ^4.0.0 + checksum: f3d84ced58a901b4fcc29c846983108c426631fe47e94872868b65565495f7bee7b3defd68923bd480582771fd4bbe819217803a164a618ad76f1d22f666f41e + languageName: node + linkType: hard + +"globby@npm:^14.0.0": + version: 14.0.1 + resolution: "globby@npm:14.0.1" + dependencies: + "@sindresorhus/merge-streams": ^2.1.0 + fast-glob: ^3.3.2 + ignore: ^5.2.4 + path-type: ^5.0.0 + slash: ^5.1.0 + unicorn-magic: ^0.1.0 + checksum: 33568444289afb1135ad62d52d5e8412900cec620e3b6ece533afa46d004066f14b97052b643833d7cf4ee03e7fac571430130cde44c333df91a45d313105170 + languageName: node + linkType: hard + +"gopd@npm:^1.0.1": + version: 1.0.1 + resolution: "gopd@npm:1.0.1" + dependencies: + get-intrinsic: ^1.1.3 + checksum: a5ccfb8806e0917a94e0b3de2af2ea4979c1da920bc381667c260e00e7cafdbe844e2cb9c5bcfef4e5412e8bf73bab837285bc35c7ba73aaaf0134d4583393a6 + languageName: node + linkType: hard + +"got@npm:^12.1.0": + version: 12.6.1 + resolution: "got@npm:12.6.1" + dependencies: + "@sindresorhus/is": ^5.2.0 + "@szmarczak/http-timer": ^5.0.1 + cacheable-lookup: ^7.0.0 + cacheable-request: ^10.2.8 + decompress-response: ^6.0.0 + form-data-encoder: ^2.1.2 + get-stream: ^6.0.1 + http2-wrapper: ^2.1.10 + lowercase-keys: ^3.0.0 + p-cancelable: ^3.0.0 + responselike: ^3.0.0 + checksum: 3c37f5d858aca2859f9932e7609d35881d07e7f2d44c039d189396f0656896af6c77c22f2c51c563f8918be483f60ff41e219de742ab4642d4b106711baccbd5 + languageName: node + linkType: hard + +"got@npm:^9.6.0": + version: 9.6.0 + resolution: "got@npm:9.6.0" + dependencies: + "@sindresorhus/is": ^0.14.0 + "@szmarczak/http-timer": ^1.1.2 + cacheable-request: ^6.0.0 + decompress-response: ^3.3.0 + duplexer3: ^0.1.4 + get-stream: ^4.1.0 + lowercase-keys: ^1.0.1 + mimic-response: ^1.0.1 + p-cancelable: ^1.0.0 + to-readable-stream: ^1.0.0 + url-parse-lax: ^3.0.0 + checksum: 941807bd9704bacf5eb401f0cc1212ffa1f67c6642f2d028fd75900471c221b1da2b8527f4553d2558f3faeda62ea1cf31665f8b002c6137f5de8732f07370b0 + languageName: node + linkType: hard + +"graceful-fs@npm:4.2.10": + version: 4.2.10 + resolution: "graceful-fs@npm:4.2.10" + checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 + languageName: node + linkType: hard + +"graphemer@npm:^1.4.0": + version: 1.4.0 + resolution: "graphemer@npm:1.4.0" + checksum: bab8f0be9b568857c7bec9fda95a89f87b783546d02951c40c33f84d05bb7da3fd10f863a9beb901463669b6583173a8c8cc6d6b306ea2b9b9d5d3d943c3a673 + languageName: node + linkType: hard + +"gray-matter@npm:^4.0.3": + version: 4.0.3 + resolution: "gray-matter@npm:4.0.3" + dependencies: + js-yaml: ^3.13.1 + kind-of: ^6.0.2 + section-matter: ^1.0.0 + strip-bom-string: ^1.0.0 + checksum: 37717bd424344487d655392251ce8d8878a1275ee087003e61208fba3bfd59cbb73a85b2159abf742ae95e23db04964813fdc33ae18b074208428b2528205222 + languageName: node + linkType: hard + +"gzip-size@npm:^6.0.0": + version: 6.0.0 + resolution: "gzip-size@npm:6.0.0" + dependencies: + duplexer: ^0.1.2 + checksum: 2df97f359696ad154fc171dcb55bc883fe6e833bca7a65e457b9358f3cb6312405ed70a8da24a77c1baac0639906cd52358dc0ce2ec1a937eaa631b934c94194 + languageName: node + linkType: hard + +"handle-thing@npm:^2.0.0": + version: 2.0.1 + resolution: "handle-thing@npm:2.0.1" + checksum: 68071f313062315cd9dce55710e9496873945f1dd425107007058fc1629f93002a7649fcc3e464281ce02c7e809a35f5925504ab8105d972cf649f1f47cb7d6c + languageName: node + linkType: hard + +"hardhat@npm:^2.22.6": + version: 2.22.6 + resolution: "hardhat@npm:2.22.6" + dependencies: + "@ethersproject/abi": ^5.1.2 + "@metamask/eth-sig-util": ^4.0.0 + "@nomicfoundation/edr": ^0.4.1 + "@nomicfoundation/ethereumjs-common": 4.0.4 + "@nomicfoundation/ethereumjs-tx": 5.0.4 + "@nomicfoundation/ethereumjs-util": 9.0.4 + "@nomicfoundation/solidity-analyzer": ^0.1.0 + "@sentry/node": ^5.18.1 + "@types/bn.js": ^5.1.0 + "@types/lru-cache": ^5.1.0 + adm-zip: ^0.4.16 + aggregate-error: ^3.0.0 + ansi-escapes: ^4.3.0 + boxen: ^5.1.2 + chalk: ^2.4.2 + chokidar: ^3.4.0 + ci-info: ^2.0.0 + debug: ^4.1.1 + enquirer: ^2.3.0 + env-paths: ^2.2.0 + ethereum-cryptography: ^1.0.3 + ethereumjs-abi: ^0.6.8 + find-up: ^2.1.0 + fp-ts: 1.19.3 + fs-extra: ^7.0.1 + glob: 7.2.0 + immutable: ^4.0.0-rc.12 + io-ts: 1.10.4 + keccak: ^3.0.2 + lodash: ^4.17.11 + mnemonist: ^0.38.0 + mocha: ^10.0.0 + p-map: ^4.0.0 + raw-body: ^2.4.1 + resolve: 1.17.0 + semver: ^6.3.0 + solc: 0.8.26 + source-map-support: ^0.5.13 + stacktrace-parser: ^0.1.10 + tsort: 0.0.1 + undici: ^5.14.0 + uuid: ^8.3.2 + ws: ^7.4.6 + peerDependencies: + ts-node: "*" + typescript: "*" + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + bin: + hardhat: internal/cli/bootstrap.js + checksum: 5aec1824db3575d63754de18c2629bcd820bc836d836f8a6346bcd9aa2ae4c397e090c43ea482ee765b704e018001015b5c84c5ded301a6a1144129c1a4c509b + languageName: node + linkType: hard + +"has-flag@npm:^3.0.0": + version: 3.0.0 + resolution: "has-flag@npm:3.0.0" + checksum: 4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b + languageName: node + linkType: hard + +"has-flag@npm:^4.0.0": + version: 4.0.0 + resolution: "has-flag@npm:4.0.0" + checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad + languageName: node + linkType: hard + +"has-own-prop@npm:^2.0.0": + version: 2.0.0 + resolution: "has-own-prop@npm:2.0.0" + checksum: ca6336e85ead2295c9603880cbc199e2d3ff7eaea0e9035d68fbc79892e9cf681abc62c0909520f112c671dad9961be2173b21dff951358cc98425c560e789e0 + languageName: node + linkType: hard + +"has-property-descriptors@npm:^1.0.0": + version: 1.0.1 + resolution: "has-property-descriptors@npm:1.0.1" + dependencies: + get-intrinsic: ^1.2.2 + checksum: 2bcc6bf6ec6af375add4e4b4ef586e43674850a91ad4d46666d0b28ba8e1fd69e424c7677d24d60f69470ad0afaa2f3197f508b20b0bb7dd99a8ab77ffc4b7c4 + languageName: node + linkType: hard + +"has-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "has-proto@npm:1.0.1" + checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": + version: 1.0.3 + resolution: "has-symbols@npm:1.0.3" + checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.0": + version: 1.0.0 + resolution: "has-tostringtag@npm:1.0.0" + dependencies: + has-symbols: ^1.0.2 + checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c + languageName: node + linkType: hard + +"has-yarn@npm:^2.1.0": + version: 2.1.0 + resolution: "has-yarn@npm:2.1.0" + checksum: 5eb1d0bb8518103d7da24532bdbc7124ffc6d367b5d3c10840b508116f2f1bcbcf10fd3ba843ff6e2e991bdf9969fd862d42b2ed58aade88343326c950b7e7f7 + languageName: node + linkType: hard + +"has-yarn@npm:^3.0.0": + version: 3.0.0 + resolution: "has-yarn@npm:3.0.0" + checksum: b9e14e78e0a37bc070550c862b201534287bc10e62a86ec9c1f455ffb082db42817ce9aed914bd73f1d589bbf268520e194629ff2f62ff6b98a482c4bd2dcbfb + languageName: node + linkType: hard + +"hash-base@npm:^3.0.0": + version: 3.1.0 + resolution: "hash-base@npm:3.1.0" + dependencies: + inherits: ^2.0.4 + readable-stream: ^3.6.0 + safe-buffer: ^5.2.0 + checksum: 26b7e97ac3de13cb23fc3145e7e3450b0530274a9562144fc2bf5c1e2983afd0e09ed7cc3b20974ba66039fad316db463da80eb452e7373e780cbee9a0d2f2dc + languageName: node + linkType: hard + +"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3, hash.js@npm:^1.1.7": + version: 1.1.7 + resolution: "hash.js@npm:1.1.7" + dependencies: + inherits: ^2.0.3 + minimalistic-assert: ^1.0.1 + checksum: e350096e659c62422b85fa508e4b3669017311aa4c49b74f19f8e1bc7f3a54a584fdfd45326d4964d6011f2b2d882e38bea775a96046f2a61b7779a979629d8f + languageName: node + linkType: hard + +"hasown@npm:^2.0.0": + version: 2.0.0 + resolution: "hasown@npm:2.0.0" + dependencies: + function-bind: ^1.1.2 + checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176 + languageName: node + linkType: hard + +"hast-to-hyperscript@npm:^9.0.0": + version: 9.0.1 + resolution: "hast-to-hyperscript@npm:9.0.1" + dependencies: + "@types/unist": ^2.0.3 + comma-separated-tokens: ^1.0.0 + property-information: ^5.3.0 + space-separated-tokens: ^1.0.0 + style-to-object: ^0.3.0 + unist-util-is: ^4.0.0 + web-namespaces: ^1.0.0 + checksum: de570d789853018fff2fd38fc096549b9814e366b298f60c90c159a57018230eefc44d46a246027b0e2426ed9e99f2e270050bc183d5bdfe4c9487c320b392cd + languageName: node + linkType: hard + +"hast-util-from-dom@npm:^5.0.0": + version: 5.0.0 + resolution: "hast-util-from-dom@npm:5.0.0" + dependencies: + "@types/hast": ^3.0.0 + hastscript: ^8.0.0 + web-namespaces: ^2.0.0 + checksum: bf8f96c480a598b42156227be2210bbb7a08da519ae4d57814385c8560b01e2b6b5fbde2afce808ce7ba7c5cd172822d4285b8f5edde2d13089bc9c3177c0d09 + languageName: node + linkType: hard + +"hast-util-from-html-isomorphic@npm:^2.0.0": + version: 2.0.0 + resolution: "hast-util-from-html-isomorphic@npm:2.0.0" + dependencies: + "@types/hast": ^3.0.0 + hast-util-from-dom: ^5.0.0 + hast-util-from-html: ^2.0.0 + unist-util-remove-position: ^5.0.0 + checksum: a98d02890bd1b5a804a1b2aaacd0332a6563f2a8df620450e38ab8962728cda0485cd29435824840621d1e653943776864e912d78d24cce6a7f484011ee7cef0 + languageName: node + linkType: hard + +"hast-util-from-html@npm:^2.0.0": + version: 2.0.1 + resolution: "hast-util-from-html@npm:2.0.1" + dependencies: + "@types/hast": ^3.0.0 + devlop: ^1.1.0 + hast-util-from-parse5: ^8.0.0 + parse5: ^7.0.0 + vfile: ^6.0.0 + vfile-message: ^4.0.0 + checksum: 8decdec1f2750d3d8d4933a4d06d78846a9fb3c97cded07395d160adae22bacfc69eaf113fd95a6ad696d1e5877580f2ac83a4161fa9f3becb0fafe2cec8b0ea + languageName: node + linkType: hard + +"hast-util-from-parse5@npm:^6.0.0": + version: 6.0.1 + resolution: "hast-util-from-parse5@npm:6.0.1" + dependencies: + "@types/parse5": ^5.0.0 + hastscript: ^6.0.0 + property-information: ^5.0.0 + vfile: ^4.0.0 + vfile-location: ^3.2.0 + web-namespaces: ^1.0.0 + checksum: 4daa78201468af7779161e7caa2513c329830778e0528481ab16b3e1bcef4b831f6285b526aacdddbee802f3bd9d64df55f80f010591ea1916da535e3a923b83 + languageName: node + linkType: hard + +"hast-util-from-parse5@npm:^8.0.0": + version: 8.0.1 + resolution: "hast-util-from-parse5@npm:8.0.1" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + hastscript: ^8.0.0 + property-information: ^6.0.0 + vfile: ^6.0.0 + vfile-location: ^5.0.0 + web-namespaces: ^2.0.0 + checksum: fdd1ab8b03af13778ecb94ef9a58b1e3528410cdfceb3d6bb7600508967d0d836b451bc7bc3baf66efb7c730d3d395eea4bb1b30352b0162823d9f0de976774b + languageName: node + linkType: hard + +"hast-util-is-element@npm:^1.1.0": + version: 1.1.0 + resolution: "hast-util-is-element@npm:1.1.0" + checksum: 30fad3f65e7ab2f0efd5db9e7344d0820b70971988dfe79f62d8447598b2a1ce8a59cd4bfc05ae0d9a1c451b9b53cbe1023743d7eac764d64720b6b73475f62f + languageName: node + linkType: hard + +"hast-util-is-element@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-is-element@npm:3.0.0" + dependencies: + "@types/hast": ^3.0.0 + checksum: 82569a420eda5877c52fdbbdbe26675f012c02d70813dfd19acffdee328e42e4bd0b7ae34454cfcbcb932b2bedbd7ddc119f943a0cfb234120f9456d6c0c4331 + languageName: node + linkType: hard + +"hast-util-parse-selector@npm:^2.0.0": + version: 2.2.5 + resolution: "hast-util-parse-selector@npm:2.2.5" + checksum: 22ee4afbd11754562144cb3c4f3ec52524dafba4d90ee52512902d17cf11066d83b38f7bdf6ca571bbc2541f07ba30db0d234657b6ecb8ca4631587466459605 + languageName: node + linkType: hard + +"hast-util-parse-selector@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-parse-selector@npm:4.0.0" + dependencies: + "@types/hast": ^3.0.0 + checksum: 76087670d3b0b50b23a6cb70bca53a6176d6608307ccdbb3ed18b650b82e7c3513bfc40348f1389dc0c5ae872b9a768851f4335f44654abd7deafd6974c52402 + languageName: node + linkType: hard + +"hast-util-raw@npm:6.0.1": + version: 6.0.1 + resolution: "hast-util-raw@npm:6.0.1" + dependencies: + "@types/hast": ^2.0.0 + hast-util-from-parse5: ^6.0.0 + hast-util-to-parse5: ^6.0.0 + html-void-elements: ^1.0.0 + parse5: ^6.0.0 + unist-util-position: ^3.0.0 + vfile: ^4.0.0 + web-namespaces: ^1.0.0 + xtend: ^4.0.0 + zwitch: ^1.0.0 + checksum: f6d960644f9fbbe0b92d0227b20a24d659cce021d5f9fd218e077154931b4524ee920217b7fd5a45ec2736ec1dee53de9209fe449f6f89454c01d225ff0e7851 + languageName: node + linkType: hard + +"hast-util-raw@npm:^9.0.0": + version: 9.0.1 + resolution: "hast-util-raw@npm:9.0.1" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + "@ungap/structured-clone": ^1.0.0 + hast-util-from-parse5: ^8.0.0 + hast-util-to-parse5: ^8.0.0 + html-void-elements: ^3.0.0 + mdast-util-to-hast: ^13.0.0 + parse5: ^7.0.0 + unist-util-position: ^5.0.0 + unist-util-visit: ^5.0.0 + vfile: ^6.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 4b486eb4782eafb471ae639d45c14ac8797676518cf5da16adc973f52d7b8e1075a1451558c023b390820bd9fd213213e6248a2dae71b68ac5040b277509b8d9 + languageName: node + linkType: hard + +"hast-util-to-estree@npm:^3.0.0": + version: 3.1.0 + resolution: "hast-util-to-estree@npm:3.1.0" + dependencies: + "@types/estree": ^1.0.0 + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + estree-util-attach-comments: ^3.0.0 + estree-util-is-identifier-name: ^3.0.0 + hast-util-whitespace: ^3.0.0 + mdast-util-mdx-expression: ^2.0.0 + mdast-util-mdx-jsx: ^3.0.0 + mdast-util-mdxjs-esm: ^2.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + style-to-object: ^0.4.0 + unist-util-position: ^5.0.0 + zwitch: ^2.0.0 + checksum: 61272f7c18c9d2a5e34df7cfd2c97cbf12f6e9d05114d60e4dedd64e5576565eb1e35c78b9213c909bb8f984f0f8e9c49b568f04bdb444b83d0bca9159e14f3c + languageName: node + linkType: hard + +"hast-util-to-jsx-runtime@npm:^2.0.0": + version: 2.3.0 + resolution: "hast-util-to-jsx-runtime@npm:2.3.0" + dependencies: + "@types/estree": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + estree-util-is-identifier-name: ^3.0.0 + hast-util-whitespace: ^3.0.0 + mdast-util-mdx-expression: ^2.0.0 + mdast-util-mdx-jsx: ^3.0.0 + mdast-util-mdxjs-esm: ^2.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + style-to-object: ^1.0.0 + unist-util-position: ^5.0.0 + vfile-message: ^4.0.0 + checksum: 599a97c6ec61c1430776813d7fb42e6f96032bf4a04dfcbb8eceef3bc8d1845ecf242387a4426b9d3f52320dbbfa26450643b81124b3d6a0b9bbb0fff4d0ba83 + languageName: node + linkType: hard + +"hast-util-to-parse5@npm:^6.0.0": + version: 6.0.0 + resolution: "hast-util-to-parse5@npm:6.0.0" + dependencies: + hast-to-hyperscript: ^9.0.0 + property-information: ^5.0.0 + web-namespaces: ^1.0.0 + xtend: ^4.0.0 + zwitch: ^1.0.0 + checksum: 91a36244e37df1d63c8b7e865ab0c0a25bb7396155602be005cf71d95c348e709568f80e0f891681a3711d733ad896e70642dc41a05b574eddf2e07d285408a8 + languageName: node + linkType: hard + +"hast-util-to-parse5@npm:^8.0.0": + version: 8.0.0 + resolution: "hast-util-to-parse5@npm:8.0.0" + dependencies: + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 137469209cb2b32b57387928878dc85310fbd5afa4807a8da69529199bb1d19044bfc95b50c3dc68d4fb2b6cb8bf99b899285597ab6ab318f50422eefd5599dd + languageName: node + linkType: hard + +"hast-util-to-text@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-to-text@npm:4.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + hast-util-is-element: ^3.0.0 + unist-util-find-after: ^5.0.0 + checksum: 3beedbdf20e2ecc9352cdd0963848b741294c1f3872d43400125bc0ca2d7938d5358081b0f9c252ec15c22368f30a4e7e6ca0ce5a57d4d2bcdd02adbf884e2af + languageName: node + linkType: hard + +"hast-util-whitespace@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-whitespace@npm:3.0.0" + dependencies: + "@types/hast": ^3.0.0 + checksum: 41d93ccce218ba935dc3c12acdf586193c35069489c8c8f50c2aa824c00dec94a3c78b03d1db40fa75381942a189161922e4b7bca700b3a2cc779634c351a1e4 + languageName: node + linkType: hard + +"hastscript@npm:^6.0.0": + version: 6.0.0 + resolution: "hastscript@npm:6.0.0" + dependencies: + "@types/hast": ^2.0.0 + comma-separated-tokens: ^1.0.0 + hast-util-parse-selector: ^2.0.0 + property-information: ^5.0.0 + space-separated-tokens: ^1.0.0 + checksum: 5e50b85af0d2cb7c17979cb1ddca75d6b96b53019dd999b39e7833192c9004201c3cee6445065620ea05d0087d9ae147a4844e582d64868be5bc6b0232dfe52d + languageName: node + linkType: hard + +"hastscript@npm:^8.0.0": + version: 8.0.0 + resolution: "hastscript@npm:8.0.0" + dependencies: + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + hast-util-parse-selector: ^4.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + checksum: ae3c20223e7b847320c0f98b6fb3c763ebe1bf3913c5805fbc176cf84553a9db1117ca34cf842a5235890b4b9ae0e94501bfdc9a9b870a5dbf5fc52426db1097 + languageName: node + linkType: hard + +"he@npm:1.2.0, he@npm:^1.2.0": + version: 1.2.0 + resolution: "he@npm:1.2.0" + bin: + he: bin/he + checksum: 3d4d6babccccd79c5c5a3f929a68af33360d6445587d628087f39a965079d84f18ce9c3d3f917ee1e3978916fc833bb8b29377c3b403f919426f91bc6965e7a7 + languageName: node + linkType: hard + +"history@npm:^4.9.0": + version: 4.10.1 + resolution: "history@npm:4.10.1" + dependencies: + "@babel/runtime": ^7.1.2 + loose-envify: ^1.2.0 + resolve-pathname: ^3.0.0 + tiny-invariant: ^1.0.2 + tiny-warning: ^1.0.0 + value-equal: ^1.0.1 + checksum: addd84bc4683929bae4400419b5af132ff4e4e9b311a0d4e224579ea8e184a6b80d7f72c55927e4fa117f69076a9e47ce082d8d0b422f1a9ddac7991490ca1d0 + languageName: node + linkType: hard + +"hmac-drbg@npm:^1.0.1": + version: 1.0.1 + resolution: "hmac-drbg@npm:1.0.1" + dependencies: + hash.js: ^1.0.3 + minimalistic-assert: ^1.0.0 + minimalistic-crypto-utils: ^1.0.1 + checksum: bd30b6a68d7f22d63f10e1888aee497d7c2c5c0bb469e66bbdac99f143904d1dfe95f8131f95b3e86c86dd239963c9d972fcbe147e7cffa00e55d18585c43fe0 + languageName: node + linkType: hard + +"hoist-non-react-statics@npm:^3.1.0": + version: 3.3.2 + resolution: "hoist-non-react-statics@npm:3.3.2" + dependencies: + react-is: ^16.7.0 + checksum: b1538270429b13901ee586aa44f4cc3ecd8831c061d06cb8322e50ea17b3f5ce4d0e2e66394761e6c8e152cd8c34fb3b4b690116c6ce2bd45b18c746516cb9e8 + languageName: node + linkType: hard + +"hpack.js@npm:^2.1.6": + version: 2.1.6 + resolution: "hpack.js@npm:2.1.6" + dependencies: + inherits: ^2.0.1 + obuf: ^1.0.0 + readable-stream: ^2.0.1 + wbuf: ^1.1.0 + checksum: 2de144115197967ad6eeee33faf41096c6ba87078703c5cb011632dcfbffeb45784569e0cf02c317bd79c48375597c8ec88c30fff5bb0b023e8f654fb6e9c06e + languageName: node + linkType: hard + +"html-entities@npm:^2.3.2, html-entities@npm:^2.4.0": + version: 2.4.0 + resolution: "html-entities@npm:2.4.0" + checksum: 25bea32642ce9ebd0eedc4d24381883ecb0335ccb8ac26379a0958b9b16652fdbaa725d70207ce54a51db24103436a698a8e454397d3ba8ad81460224751f1dc + languageName: node + linkType: hard + +"html-escaper@npm:^2.0.0, html-escaper@npm:^2.0.2": + version: 2.0.2 + resolution: "html-escaper@npm:2.0.2" + checksum: d2df2da3ad40ca9ee3a39c5cc6475ef67c8f83c234475f24d8e9ce0dc80a2c82df8e1d6fa78ddd1e9022a586ea1bd247a615e80a5cd9273d90111ddda7d9e974 + languageName: node + linkType: hard + +"html-minifier-terser@npm:^6.0.2, html-minifier-terser@npm:^6.1.0": + version: 6.1.0 + resolution: "html-minifier-terser@npm:6.1.0" + dependencies: + camel-case: ^4.1.2 + clean-css: ^5.2.2 + commander: ^8.3.0 + he: ^1.2.0 + param-case: ^3.0.4 + relateurl: ^0.2.7 + terser: ^5.10.0 + bin: + html-minifier-terser: cli.js + checksum: ac52c14006476f773204c198b64838477859dc2879490040efab8979c0207424da55d59df7348153f412efa45a0840a1ca3c757bf14767d23a15e3e389d37a93 + languageName: node + linkType: hard + +"html-minifier-terser@npm:^7.2.0": + version: 7.2.0 + resolution: "html-minifier-terser@npm:7.2.0" + dependencies: + camel-case: ^4.1.2 + clean-css: ~5.3.2 + commander: ^10.0.0 + entities: ^4.4.0 + param-case: ^3.0.4 + relateurl: ^0.2.7 + terser: ^5.15.1 + bin: + html-minifier-terser: cli.js + checksum: 39feed354b5a8aafc8e910977d68cfd961d6db330a8e1a5b16a528c86b8ee7745d8945134822cf00acf7bf0d0135bf1abad650bf308bee4ea73adb003f5b8656 + languageName: node + linkType: hard + +"html-tags@npm:^3.2.0, html-tags@npm:^3.3.1": + version: 3.3.1 + resolution: "html-tags@npm:3.3.1" + checksum: b4ef1d5a76b678e43cce46e3783d563607b1d550cab30b4f511211564574770aa8c658a400b100e588bc60b8234e59b35ff72c7851cc28f3b5403b13a2c6cbce + languageName: node + linkType: hard + +"html-void-elements@npm:^1.0.0": + version: 1.0.5 + resolution: "html-void-elements@npm:1.0.5" + checksum: 1a56f4f6cfbeb994c21701ff72b4b7f556fe784a70e5e554d1566ff775af83b91ea93f10664f039a67802d9f7b40d4a7f1ed20312bab47bd88d89bd792ea84ca + languageName: node + linkType: hard + +"html-void-elements@npm:^3.0.0": + version: 3.0.0 + resolution: "html-void-elements@npm:3.0.0" + checksum: 59be397525465a7489028afa064c55763d9cccd1d7d9f630cca47137317f0e897a9ca26cef7e745e7cff1abc44260cfa407742b243a54261dfacd42230e94fce + languageName: node + linkType: hard + +"html-webpack-plugin@npm:^5.5.0, html-webpack-plugin@npm:^5.5.3": + version: 5.5.4 + resolution: "html-webpack-plugin@npm:5.5.4" + dependencies: + "@types/html-minifier-terser": ^6.0.0 + html-minifier-terser: ^6.0.2 + lodash: ^4.17.21 + pretty-error: ^4.0.0 + tapable: ^2.0.0 + peerDependencies: + webpack: ^5.20.0 + checksum: b49befb73d67a3716fd0e6f7776b108d2b0b7050fb8221f05cd114cbae13c03150a13b7cdf5e76170be040ce7936a1cf76f7a4bfd9ebe1552b72d7889a74c374 + languageName: node + linkType: hard + +"html-webpack-plugin@npm:^5.6.0": + version: 5.6.0 + resolution: "html-webpack-plugin@npm:5.6.0" + dependencies: + "@types/html-minifier-terser": ^6.0.0 + html-minifier-terser: ^6.0.2 + lodash: ^4.17.21 + pretty-error: ^4.0.0 + tapable: ^2.0.0 + peerDependencies: + "@rspack/core": 0.x || 1.x + webpack: ^5.20.0 + peerDependenciesMeta: + "@rspack/core": + optional: true + webpack: + optional: true + checksum: 32a6e41da538e798fd0be476637d7611a5e8a98a3508f031996e9eb27804dcdc282cb01f847cf5d066f21b49cfb8e21627fcf977ffd0c9bea81cf80e5a65070d + languageName: node + linkType: hard + +"htmlparser2@npm:^6.1.0": + version: 6.1.0 + resolution: "htmlparser2@npm:6.1.0" + dependencies: + domelementtype: ^2.0.1 + domhandler: ^4.0.0 + domutils: ^2.5.2 + entities: ^2.0.0 + checksum: 81a7b3d9c3bb9acb568a02fc9b1b81ffbfa55eae7f1c41ae0bf840006d1dbf54cb3aa245b2553e2c94db674840a9f0fdad7027c9a9d01a062065314039058c4e + languageName: node + linkType: hard + +"htmlparser2@npm:^8.0.1": + version: 8.0.2 + resolution: "htmlparser2@npm:8.0.2" + dependencies: + domelementtype: ^2.3.0 + domhandler: ^5.0.3 + domutils: ^3.0.1 + entities: ^4.4.0 + checksum: 29167a0f9282f181da8a6d0311b76820c8a59bc9e3c87009e21968264c2987d2723d6fde5a964d4b7b6cba663fca96ffb373c06d8223a85f52a6089ced942700 + languageName: node + linkType: hard + +"http-assert@npm:^1.3.0": + version: 1.5.0 + resolution: "http-assert@npm:1.5.0" + dependencies: + deep-equal: ~1.0.1 + http-errors: ~1.8.0 + checksum: 69c9b3c14cf8b2822916360a365089ce936c883c49068f91c365eccba5c141a9964d19fdda589150a480013bf503bf37d8936c732e9635819339e730ab0e7527 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 + languageName: node + linkType: hard + +"http-deceiver@npm:^1.2.7": + version: 1.2.7 + resolution: "http-deceiver@npm:1.2.7" + checksum: 64d7d1ae3a6933eb0e9a94e6f27be4af45a53a96c3c34e84ff57113787105a89fff9d1c3df263ef63add823df019b0e8f52f7121e32393bb5ce9a713bf100b41 + languageName: node + linkType: hard + +"http-errors@npm:2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + checksum: 9b0a3782665c52ce9dc658a0d1560bcb0214ba5699e4ea15aefb2a496e2ca83db03ebc42e1cce4ac1f413e4e0d2d736a3fd755772c556a9a06853ba2a0b7d920 + languageName: node + linkType: hard + +"http-errors@npm:^1.6.3, http-errors@npm:^1.7.3, http-errors@npm:~1.8.0": + version: 1.8.1 + resolution: "http-errors@npm:1.8.1" + dependencies: + depd: ~1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: ">= 1.5.0 < 2" + toidentifier: 1.0.1 + checksum: d3c7e7e776fd51c0a812baff570bdf06fe49a5dc448b700ab6171b1250e4cf7db8b8f4c0b133e4bfe2451022a5790c1ca6c2cae4094dedd6ac8304a1267f91d2 + languageName: node + linkType: hard + +"http-errors@npm:~1.6.2": + version: 1.6.3 + resolution: "http-errors@npm:1.6.3" + dependencies: + depd: ~1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: ">= 1.4.0 < 2" + checksum: a9654ee027e3d5de305a56db1d1461f25709ac23267c6dc28cdab8323e3f96caa58a9a6a5e93ac15d7285cee0c2f019378c3ada9026e7fe19c872d695f27de7c + languageName: node + linkType: hard + +"http-parser-js@npm:>=0.5.1": + version: 0.5.8 + resolution: "http-parser-js@npm:0.5.8" + checksum: 6bbdf2429858e8cf13c62375b0bfb6dc3955ca0f32e58237488bc86cd2378f31d31785fd3ac4ce93f1c74e0189cf8823c91f5cb061696214fd368d2452dc871d + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.0 + resolution: "http-proxy-agent@npm:7.0.0" + dependencies: + agent-base: ^7.1.0 + debug: ^4.3.4 + checksum: 48d4fac997917e15f45094852b63b62a46d0c8a4f0b9c6c23ca26d27b8df8d178bed88389e604745e748bd9a01f5023e25093722777f0593c3f052009ff438b6 + 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" + dependencies: + "@types/http-proxy": ^1.17.8 + http-proxy: ^1.18.1 + is-glob: ^4.0.1 + is-plain-obj: ^3.0.0 + micromatch: ^4.0.2 + peerDependencies: + "@types/express": ^4.17.13 + peerDependenciesMeta: + "@types/express": + optional: true + checksum: 2ee85bc878afa6cbf34491e972ece0f5be0a3e5c98a60850cf40d2a9a5356e1fc57aab6cff33c1fc37691b0121c3a42602d2b1956c52577e87a5b77b62ae1c3a + languageName: node + linkType: hard + +"http-proxy@npm:^1.18.1": + version: 1.18.1 + resolution: "http-proxy@npm:1.18.1" + dependencies: + eventemitter3: ^4.0.0 + follow-redirects: ^1.0.0 + requires-port: ^1.0.0 + checksum: f5bd96bf83e0b1e4226633dbb51f8b056c3e6321917df402deacec31dd7fe433914fc7a2c1831cf7ae21e69c90b3a669b8f434723e9e8b71fd68afe30737b6a5 + languageName: node + linkType: hard + +"http2-wrapper@npm:^2.1.10": + version: 2.2.1 + resolution: "http2-wrapper@npm:2.2.1" + dependencies: + quick-lru: ^5.1.1 + resolve-alpn: ^1.2.0 + checksum: e95e55e22c6fd61182ce81fecb9b7da3af680d479febe8ad870d05f7ebbc9f076e455193766f4e7934e50913bf1d8da3ba121fb5cd2928892390b58cf9d5c509 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^5.0.0": + version: 5.0.1 + resolution: "https-proxy-agent@npm:5.0.1" + dependencies: + agent-base: 6 + debug: 4 + checksum: 571fccdf38184f05943e12d37d6ce38197becdd69e58d03f43637f7fa1269cf303a7d228aa27e5b27bbd3af8f09fd938e1c91dcfefff2df7ba77c20ed8dfc765 + languageName: node + linkType: hard + +"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: + agent-base: ^7.0.2 + debug: 4 + checksum: 088969a0dd476ea7a0ed0a2cf1283013682b08f874c3bc6696c83fa061d2c157d29ef0ad3eb70a2046010bb7665573b2388d10fdcb3e410a66995e5248444292 + 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" + checksum: b87fd89fce72391625271454e70f67fe405277415b48bcc0117ca73d31fa23a4241787afdc8d67f5a116cf37258c052f59ea82daffa72364d61351423848e3b8 + languageName: node + linkType: hard + +"hyperdyperid@npm:^1.2.0": + version: 1.2.0 + resolution: "hyperdyperid@npm:1.2.0" + checksum: 210029d1c86926f09109f6317d143f8b056fc38e8dd11b0c3e3205fc6c6ff8429fb55b4b9c2bce065462719ed9d34366eced387aaa0035d93eb76b306a8547ef + languageName: node + linkType: hard + +"iconv-lite@npm:0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: ">= 2.1.2 < 3" + checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: ">= 2.1.2 < 3.0.0" + checksum: 3f60d47a5c8fc3313317edfd29a00a692cc87a19cac0159e2ce711d0ebc9019064108323b5e493625e25594f11c6236647d8e256fbe7a58f4a3b33b89e6d30bf + languageName: node + linkType: hard + +"icss-utils@npm:^5.0.0, icss-utils@npm:^5.1.0": + version: 5.1.0 + resolution: "icss-utils@npm:5.1.0" + peerDependencies: + postcss: ^8.1.0 + checksum: 5c324d283552b1269cfc13a503aaaa172a280f914e5b81544f3803bc6f06a3b585fb79f66f7c771a2c052db7982c18bf92d001e3b47282e3abbbb4c4cc488d68 + languageName: node + linkType: hard + +"idb-wrapper@npm:^1.5.0": + version: 1.7.2 + resolution: "idb-wrapper@npm:1.7.2" + checksum: a5fa3a771166205e2d5d2b93c66bd31571dada3526b59bc0f8583efb091b6b327125f1a964a25a281b85ef1c44af10a3c511652632ad3adf8229a161132d66ae + languageName: node + linkType: hard + +"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e + languageName: node + linkType: hard + +"ignore@npm:^5.2.0, ignore@npm:^5.2.4": + version: 5.3.0 + resolution: "ignore@npm:5.3.0" + checksum: 2736da6621f14ced652785cb05d86301a66d70248597537176612bd0c8630893564bd5f6421f8806b09e8472e75c591ef01672ab8059c07c6eb2c09cefe04bf9 + languageName: node + linkType: hard + +"image-size@npm:^1.0.1, image-size@npm:^1.0.2": + version: 1.0.2 + resolution: "image-size@npm:1.0.2" + dependencies: + queue: 6.0.2 + bin: + image-size: bin/image-size.js + checksum: 01745fdb47f87cecf538e69c63f9adc5bfab30a345345c2de91105f3afbd1bfcfba1256af02bf3323077b33b0004469a837e077bf0cbb9c907e9c1e9e7547585 + languageName: node + linkType: hard + +"immediate@npm:^3.2.3": + version: 3.3.0 + resolution: "immediate@npm:3.3.0" + checksum: 634b4305101e2452eba6c07d485bf3e415995e533c94b9c3ffbc37026fa1be34def6e4f2276b0dc2162a3f91628564a4bfb26280278b89d3ee54624e854d2f5f + languageName: node + linkType: hard + +"immer@npm:^9.0.7": + version: 9.0.21 + resolution: "immer@npm:9.0.21" + checksum: 70e3c274165995352f6936695f0ef4723c52c92c92dd0e9afdfe008175af39fa28e76aafb3a2ca9d57d1fb8f796efc4dd1e1cc36f18d33fa5b74f3dfb0375432 + languageName: node + linkType: hard + +"immutable@npm:^4.0.0-rc.12": + version: 4.3.4 + resolution: "immutable@npm:4.3.4" + checksum: de3edd964c394bab83432429d3fb0b4816b42f56050f2ca913ba520bd3068ec3e504230d0800332d3abc478616e8f55d3787424a90d0952e6aba864524f1afc3 + languageName: node + linkType: hard + +"import-fresh@npm:^3.1.0, import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": + version: 3.3.0 + resolution: "import-fresh@npm:3.3.0" + dependencies: + parent-module: ^1.0.0 + resolve-from: ^4.0.0 + checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa + languageName: node + linkType: hard + +"import-lazy@npm:^2.1.0": + version: 2.1.0 + resolution: "import-lazy@npm:2.1.0" + checksum: 05294f3b9dd4971d3a996f0d2f176410fb6745d491d6e73376429189f5c1c3d290548116b2960a7cf3e89c20cdf11431739d1d2d8c54b84061980795010e803a + languageName: node + linkType: hard + +"import-lazy@npm:^4.0.0": + version: 4.0.0 + resolution: "import-lazy@npm:4.0.0" + checksum: 22f5e51702134aef78890156738454f620e5fe7044b204ebc057c614888a1dd6fdf2ede0fdcca44d5c173fd64f65c985f19a51775b06967ef58cc3d26898df07 + languageName: node + linkType: hard + +"import-local@npm:^3.0.2": + version: 3.1.0 + resolution: "import-local@npm:3.1.0" + dependencies: + pkg-dir: ^4.2.0 + resolve-cwd: ^3.0.0 + bin: + import-local-fixture: fixtures/cli.js + checksum: bfcdb63b5e3c0e245e347f3107564035b128a414c4da1172a20dc67db2504e05ede4ac2eee1252359f78b0bfd7b19ef180aec427c2fce6493ae782d73a04cddd + languageName: node + linkType: hard + +"import-meta-resolve@npm:^4.0.0": + version: 4.0.0 + resolution: "import-meta-resolve@npm:4.0.0" + checksum: 51c50115fd38e9ba21736f8d7543a58446b92d2cb5f38c9b5ec72426afeb2fb790f82051560a0f16323f44dd73d8d37c07eab5f8dc4635bcdb401daa36727b1a + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 + languageName: node + linkType: hard + +"indexof@npm:~0.0.1": + version: 0.0.1 + resolution: "indexof@npm:0.0.1" + checksum: 0fb04e8b147b8585d981a6df1564f25bb3678d6fa74e33e5cecc1464b10f78e15e8ef6bb688f135fe5c2844a128fac8a7831cbe5adc81fdcf12681b093dfcc25 + languageName: node + linkType: hard + +"infima@npm:0.2.0-alpha.44": + version: 0.2.0-alpha.44 + resolution: "infima@npm:0.2.0-alpha.44" + checksum: e9871f4056c0c8b311fcd32e2864d23a8f6807af5ff32d3c4d8271ad9971b5a7ea5016787a6b215893bb3e9f5f14326816bc05151d576dd375b0d79279cdfa8b + languageName: node + linkType: hard + +"inflation@npm:^2.0.0": + version: 2.1.0 + resolution: "inflation@npm:2.1.0" + checksum: 80c1b5d9ec408105a85f0623c824d668ddf0cadafd8d9716c0737990e5a712ae5f7d6bb0ff216b6648eccb9c6ac69fe06c0d8c58456d168db5bf550c89dd74ed + languageName: node + linkType: hard + +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: ^1.3.0 + wrappy: 1 + checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd + languageName: node + linkType: hard + +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.0, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.1, inherits@npm:~2.0.3": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 + languageName: node + linkType: hard + +"inherits@npm:2.0.3": + version: 2.0.3 + resolution: "inherits@npm:2.0.3" + checksum: 78cb8d7d850d20a5e9a7f3620db31483aa00ad5f722ce03a55b110e5a723539b3716a3b463e2b96ce3fe286f33afc7c131fa2f91407528ba80cea98a7545d4c0 + languageName: node + linkType: hard + +"ini@npm:2.0.0": + version: 2.0.0 + resolution: "ini@npm:2.0.0" + checksum: e7aadc5fb2e4aefc666d74ee2160c073995a4061556b1b5b4241ecb19ad609243b9cceafe91bae49c219519394bbd31512516cb22a3b1ca6e66d869e0447e84e + languageName: node + linkType: hard + +"ini@npm:4.1.1": + version: 4.1.1 + resolution: "ini@npm:4.1.1" + checksum: 0e5909554074fbc31824fa5415b0f604de4a665514c96a897a77bf77353a7ad4743927321270e9d0610a9d510ccd1f3cd77422f7cc80d8f4542dbce75476fb6d + languageName: node + linkType: hard + +"ini@npm:^1.3.4, ini@npm:^1.3.5, ini@npm:~1.3.0": + version: 1.3.8 + resolution: "ini@npm:1.3.8" + checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 + languageName: node + linkType: hard + +"inline-style-parser@npm:0.1.1": + version: 0.1.1 + resolution: "inline-style-parser@npm:0.1.1" + checksum: 5d545056a3e1f2bf864c928a886a0e1656a3517127d36917b973de581bd54adc91b4bf1febcb0da054f204b4934763f1a4e09308b4d55002327cf1d48ac5d966 + languageName: node + linkType: hard + +"inline-style-parser@npm:0.2.2": + version: 0.2.2 + resolution: "inline-style-parser@npm:0.2.2" + checksum: 698893d6542d4e7c0377936a1c7daec34a197765bd77c5599384756a95ce8804e6b79347b783aa591d5e9c6f3d33dae74c6d4cad3a94647eb05f3a785e927a3f + languageName: node + linkType: hard + +"integration-tests@workspace:compiler/integration-tests": + version: 0.0.0-use.local + resolution: "integration-tests@workspace:compiler/integration-tests" + dependencies: + "@aztec/bb.js": 0.66.0 + "@noir-lang/noir_js": "workspace:*" + "@noir-lang/noir_wasm": "workspace:*" + "@nomicfoundation/hardhat-chai-matchers": ^2.0.0 + "@nomicfoundation/hardhat-ethers": ^3.0.0 + "@web/dev-server-esbuild": ^0.3.6 + "@web/dev-server-import-maps": ^0.2.0 + "@web/test-runner": ^0.18.1 + "@web/test-runner-playwright": ^0.11.0 + eslint: ^8.57.0 + eslint-plugin-prettier: ^5.1.3 + ethers: ^6.7.1 + hardhat: ^2.22.6 + prettier: 3.2.5 + smol-toml: ^1.1.2 + toml: ^3.0.0 + tslog: ^4.9.2 + languageName: unknown + linkType: soft + +"interpret@npm:^1.0.0": + version: 1.4.0 + resolution: "interpret@npm:1.4.0" + checksum: 2e5f51268b5941e4a17e4ef0575bc91ed0ab5f8515e3cf77486f7c14d13f3010df9c0959f37063dcc96e78d12dc6b0bb1b9e111cdfe69771f4656d2993d36155 + languageName: node + linkType: hard + +"interpret@npm:^3.1.1": + version: 3.1.1 + resolution: "interpret@npm:3.1.1" + checksum: 35cebcf48c7351130437596d9ab8c8fe131ce4038da4561e6d665f25640e0034702a031cf7e3a5cea60ac7ac548bf17465e0571ede126f3d3a6933152171ac82 + languageName: node + linkType: hard + +"invariant@npm:^2.2.4": + version: 2.2.4 + resolution: "invariant@npm:2.2.4" + dependencies: + loose-envify: ^1.0.0 + checksum: cc3182d793aad82a8d1f0af697b462939cb46066ec48bbf1707c150ad5fad6406137e91a262022c269702e01621f35ef60269f6c0d7fd178487959809acdfb14 + languageName: node + linkType: hard + +"io-ts@npm:1.10.4": + version: 1.10.4 + resolution: "io-ts@npm:1.10.4" + dependencies: + fp-ts: ^1.0.0 + checksum: 619134006778f7ca42693716ade7fc1a383079e7848bbeabc67a0e4ac9139cda6b2a88a052d539ab7d554033ee2ffe4dab5cb96b958c83fee2dff73d23f03e88 + languageName: node + linkType: hard + +"ip@npm:^1.1.5, ip@npm:^1.1.8": + version: 1.1.8 + resolution: "ip@npm:1.1.8" + checksum: a2ade53eb339fb0cbe9e69a44caab10d6e3784662285eb5d2677117ee4facc33a64679051c35e0dfdb1a3983a51ce2f5d2cb36446d52e10d01881789b76e28fb + languageName: node + linkType: hard + +"ip@npm:^2.0.0": + version: 2.0.0 + resolution: "ip@npm:2.0.0" + checksum: cfcfac6b873b701996d71ec82a7dd27ba92450afdb421e356f44044ed688df04567344c36cbacea7d01b1c39a4c732dc012570ebe9bebfb06f27314bca625349 + languageName: node + linkType: hard + +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: f88d3825981486f5a1942414c8d77dd6674dd71c065adcfa46f578d677edcb99fda25af42675cb59db492fdf427b34a5abfcde3982da11a8fd83a500b41cfe77 + languageName: node + linkType: hard + +"ipaddr.js@npm:^2.0.1, ipaddr.js@npm:^2.1.0": + version: 2.1.0 + resolution: "ipaddr.js@npm:2.1.0" + checksum: 807a054f2bd720c4d97ee479d6c9e865c233bea21f139fb8dabd5a35c4226d2621c42e07b4ad94ff3f82add926a607d8d9d37c625ad0319f0e08f9f2bd1968e2 + languageName: node + linkType: hard + +"is-alphabetical@npm:1.0.4, is-alphabetical@npm:^1.0.0": + version: 1.0.4 + resolution: "is-alphabetical@npm:1.0.4" + checksum: 6508cce44fd348f06705d377b260974f4ce68c74000e7da4045f0d919e568226dc3ce9685c5a2af272195384df6930f748ce9213fc9f399b5d31b362c66312cb + languageName: node + linkType: hard + +"is-alphabetical@npm:^2.0.0": + version: 2.0.1 + resolution: "is-alphabetical@npm:2.0.1" + checksum: 56207db8d9de0850f0cd30f4966bf731eb82cedfe496cbc2e97e7c3bacaf66fc54a972d2d08c0d93bb679cb84976a05d24c5ad63de56fabbfc60aadae312edaa + languageName: node + linkType: hard + +"is-alphanumerical@npm:^1.0.0": + version: 1.0.4 + resolution: "is-alphanumerical@npm:1.0.4" + dependencies: + is-alphabetical: ^1.0.0 + is-decimal: ^1.0.0 + checksum: e2e491acc16fcf5b363f7c726f666a9538dba0a043665740feb45bba1652457a73441e7c5179c6768a638ed396db3437e9905f403644ec7c468fb41f4813d03f + languageName: node + linkType: hard + +"is-alphanumerical@npm:^2.0.0": + version: 2.0.1 + resolution: "is-alphanumerical@npm:2.0.1" + dependencies: + is-alphabetical: ^2.0.0 + is-decimal: ^2.0.0 + checksum: 87acc068008d4c9c4e9f5bd5e251041d42e7a50995c77b1499cf6ed248f971aadeddb11f239cabf09f7975ee58cac7a48ffc170b7890076d8d227b24a68663c9 + languageName: node + linkType: hard + +"is-arguments@npm:^1.0.4": + version: 1.1.1 + resolution: "is-arguments@npm:1.1.1" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: 7f02700ec2171b691ef3e4d0e3e6c0ba408e8434368504bb593d0d7c891c0dbfda6d19d30808b904a6cb1929bca648c061ba438c39f296c2a8ca083229c49f27 + languageName: node + linkType: hard + +"is-arrayish@npm:^0.2.1": + version: 0.2.1 + resolution: "is-arrayish@npm:0.2.1" + checksum: eef4417e3c10e60e2c810b6084942b3ead455af16c4509959a27e490e7aee87cfb3f38e01bbde92220b528a0ee1a18d52b787e1458ee86174d8c7f0e58cd488f + languageName: node + linkType: hard + +"is-binary-path@npm:~2.1.0": + version: 2.1.0 + resolution: "is-binary-path@npm:2.1.0" + dependencies: + binary-extensions: ^2.0.0 + checksum: 84192eb88cff70d320426f35ecd63c3d6d495da9d805b19bc65b518984b7c0760280e57dbf119b7e9be6b161784a5a673ab2c6abe83abb5198a432232ad5b35c + languageName: node + linkType: hard + +"is-buffer@npm:^2.0.0": + version: 2.0.5 + resolution: "is-buffer@npm:2.0.5" + checksum: 764c9ad8b523a9f5a32af29bdf772b08eb48c04d2ad0a7240916ac2688c983bf5f8504bf25b35e66240edeb9d9085461f9b5dae1f3d2861c6b06a65fe983de42 + languageName: node + linkType: hard + +"is-builtin-module@npm:^3.2.1": + version: 3.2.1 + resolution: "is-builtin-module@npm:3.2.1" + dependencies: + builtin-modules: ^3.3.0 + checksum: e8f0ffc19a98240bda9c7ada84d846486365af88d14616e737d280d378695c8c448a621dcafc8332dbf0fcd0a17b0763b845400709963fa9151ddffece90ae88 + languageName: node + linkType: hard + +"is-callable@npm:^1.1.3": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac + languageName: node + linkType: hard + +"is-ci@npm:^2.0.0": + version: 2.0.0 + resolution: "is-ci@npm:2.0.0" + dependencies: + ci-info: ^2.0.0 + bin: + is-ci: bin.js + checksum: 77b869057510f3efa439bbb36e9be429d53b3f51abd4776eeea79ab3b221337fe1753d1e50058a9e2c650d38246108beffb15ccfd443929d77748d8c0cc90144 + languageName: node + linkType: hard + +"is-ci@npm:^3.0.1": + version: 3.0.1 + resolution: "is-ci@npm:3.0.1" + dependencies: + ci-info: ^3.2.0 + bin: + is-ci: bin.js + checksum: 192c66dc7826d58f803ecae624860dccf1899fc1f3ac5505284c0a5cf5f889046ffeb958fa651e5725d5705c5bcb14f055b79150ea5fcad7456a9569de60260e + languageName: node + linkType: hard + +"is-core-module@npm:^2.13.0": + version: 2.13.1 + resolution: "is-core-module@npm:2.13.1" + dependencies: + hasown: ^2.0.0 + checksum: 256559ee8a9488af90e4bad16f5583c6d59e92f0742e9e8bb4331e758521ee86b810b93bae44f390766ffbc518a0488b18d9dab7da9a5ff997d499efc9403f7c + languageName: node + linkType: hard + +"is-decimal@npm:^1.0.0": + version: 1.0.4 + resolution: "is-decimal@npm:1.0.4" + checksum: ed483a387517856dc395c68403a10201fddcc1b63dc56513fbe2fe86ab38766120090ecdbfed89223d84ca8b1cd28b0641b93cb6597b6e8f4c097a7c24e3fb96 + languageName: node + linkType: hard + +"is-decimal@npm:^2.0.0": + version: 2.0.1 + resolution: "is-decimal@npm:2.0.1" + checksum: 97132de7acdce77caa7b797632970a2ecd649a88e715db0e4dbc00ab0708b5e7574ba5903962c860cd4894a14fd12b100c0c4ac8aed445cf6f55c6cf747a4158 + languageName: node + linkType: hard + +"is-docker@npm:^2.0.0, is-docker@npm:^2.1.1": + version: 2.2.1 + resolution: "is-docker@npm:2.2.1" + bin: + is-docker: cli.js + checksum: 3fef7ddbf0be25958e8991ad941901bf5922ab2753c46980b60b05c1bf9c9c2402d35e6dc32e4380b980ef5e1970a5d9d5e5aa2e02d77727c3b6b5e918474c56 + languageName: node + linkType: hard + +"is-docker@npm:^3.0.0": + version: 3.0.0 + resolution: "is-docker@npm:3.0.0" + bin: + is-docker: cli.js + checksum: b698118f04feb7eaf3338922bd79cba064ea54a1c3db6ec8c0c8d8ee7613e7e5854d802d3ef646812a8a3ace81182a085dfa0a71cc68b06f3fa794b9783b3c90 + languageName: node + linkType: hard + +"is-extendable@npm:^0.1.0": + version: 0.1.1 + resolution: "is-extendable@npm:0.1.1" + checksum: 3875571d20a7563772ecc7a5f36cb03167e9be31ad259041b4a8f73f33f885441f778cee1f1fe0085eb4bc71679b9d8c923690003a36a6a5fdf8023e6e3f0672 + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 + languageName: node + linkType: hard + +"is-generator-function@npm:^1.0.7": + version: 1.0.10 + resolution: "is-generator-function@npm:1.0.10" + dependencies: + has-tostringtag: ^1.0.0 + checksum: d54644e7dbaccef15ceb1e5d91d680eb5068c9ee9f9eb0a9e04173eb5542c9b51b5ab52c5537f5703e48d5fddfd376817c1ca07a84a407b7115b769d4bdde72b + languageName: node + linkType: hard + +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: ^2.1.1 + checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 + languageName: node + linkType: hard + +"is-hex-prefixed@npm:1.0.0": + version: 1.0.0 + resolution: "is-hex-prefixed@npm:1.0.0" + checksum: 5ac58e6e528fb029cc43140f6eeb380fad23d0041cc23154b87f7c9a1b728bcf05909974e47248fd0b7fcc11ba33cf7e58d64804883056fabd23e2b898be41de + languageName: node + linkType: hard + +"is-hexadecimal@npm:^1.0.0": + version: 1.0.4 + resolution: "is-hexadecimal@npm:1.0.4" + checksum: a452e047587b6069332d83130f54d30da4faf2f2ebaa2ce6d073c27b5703d030d58ed9e0b729c8e4e5b52c6f1dab26781bb77b7bc6c7805f14f320e328ff8cd5 + languageName: node + linkType: hard + +"is-hexadecimal@npm:^2.0.0": + version: 2.0.1 + resolution: "is-hexadecimal@npm:2.0.1" + checksum: 66a2ea85994c622858f063f23eda506db29d92b52580709eb6f4c19550552d4dcf3fb81952e52f7cf972097237959e00adc7bb8c9400cd12886e15bf06145321 + languageName: node + linkType: hard + +"is-inside-container@npm:^1.0.0": + version: 1.0.0 + resolution: "is-inside-container@npm:1.0.0" + dependencies: + is-docker: ^3.0.0 + bin: + is-inside-container: cli.js + checksum: c50b75a2ab66ab3e8b92b3bc534e1ea72ca25766832c0623ac22d134116a98bcf012197d1caabe1d1c4bd5f84363d4aa5c36bb4b585fbcaf57be172cd10a1a03 + languageName: node + linkType: hard + +"is-installed-globally@npm:^0.4.0": + version: 0.4.0 + resolution: "is-installed-globally@npm:0.4.0" + dependencies: + global-dirs: ^3.0.0 + is-path-inside: ^3.0.2 + checksum: 3359840d5982d22e9b350034237b2cda2a12bac1b48a721912e1ab8e0631dd07d45a2797a120b7b87552759a65ba03e819f1bd63f2d7ab8657ec0b44ee0bf399 + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 + languageName: node + linkType: hard + +"is-module@npm:^1.0.0": + version: 1.0.0 + resolution: "is-module@npm:1.0.0" + checksum: 8cd5390730c7976fb4e8546dd0b38865ee6f7bacfa08dfbb2cc07219606755f0b01709d9361e01f13009bbbd8099fa2927a8ed665118a6105d66e40f1b838c3f + languageName: node + linkType: hard + +"is-nan@npm:^1.3.2": + version: 1.3.2 + resolution: "is-nan@npm:1.3.2" + dependencies: + call-bind: ^1.0.0 + define-properties: ^1.1.3 + checksum: 5dfadcef6ad12d3029d43643d9800adbba21cf3ce2ec849f734b0e14ee8da4070d82b15fdb35138716d02587c6578225b9a22779cab34888a139cc43e4e3610a + languageName: node + linkType: hard + +"is-network-error@npm:^1.0.0": + version: 1.0.1 + resolution: "is-network-error@npm:1.0.1" + checksum: 165d61500c4186c62db5a3a693d6bfa14ca40fe9b471ef4cd4f27b20ef6760880faf5386dc01ca9867531631782941fedaa94521d09959edf71f046e393c7b91 + languageName: node + linkType: hard + +"is-npm@npm:^5.0.0": + version: 5.0.0 + resolution: "is-npm@npm:5.0.0" + checksum: 9baff02b0c69a3d3c79b162cb2f9e67fb40ef6d172c16601b2e2471c21e9a4fa1fc9885a308d7bc6f3a3cd2a324c27fa0bf284c133c3349bb22571ab70d041cc + languageName: node + linkType: hard + +"is-npm@npm:^6.0.0": + version: 6.0.0 + resolution: "is-npm@npm:6.0.0" + checksum: fafe1ddc772345f5460514891bb8014376904ccdbddd59eee7525c9adcc08d426933f28b087bef3e17524da7ebf35c03ef484ff3b6ba9d5fecd8c6e6a7d4bf11 + languageName: node + linkType: hard + +"is-number@npm:^7.0.0": + version: 7.0.0 + resolution: "is-number@npm:7.0.0" + checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a + languageName: node + linkType: hard + +"is-obj@npm:^1.0.1": + version: 1.0.1 + resolution: "is-obj@npm:1.0.1" + checksum: 3ccf0efdea12951e0b9c784e2b00e77e87b2f8bd30b42a498548a8afcc11b3287342a2030c308e473e93a7a19c9ea7854c99a8832a476591c727df2a9c79796c + languageName: node + linkType: hard + +"is-obj@npm:^2.0.0": + version: 2.0.0 + resolution: "is-obj@npm:2.0.0" + checksum: c9916ac8f4621962a42f5e80e7ffdb1d79a3fab7456ceaeea394cd9e0858d04f985a9ace45be44433bf605673c8be8810540fe4cc7f4266fc7526ced95af5a08 + languageName: node + linkType: hard + +"is-object@npm:~0.1.2": + version: 0.1.2 + resolution: "is-object@npm:0.1.2" + checksum: 7e500b15f4748278ea0a8d43b1283e75e866c055e4a790389087ce652eab8a9343fd74710738f0fdf13a323c31330d65bdcc106f38e9bb7bc0b9c60ae3fd2a2d + languageName: node + linkType: hard + +"is-path-cwd@npm:^2.2.0": + version: 2.2.0 + resolution: "is-path-cwd@npm:2.2.0" + checksum: 46a840921bb8cc0dc7b5b423a14220e7db338072a4495743a8230533ce78812dc152548c86f4b828411fe98c5451959f07cf841c6a19f611e46600bd699e8048 + languageName: node + linkType: hard + +"is-path-inside@npm:^3.0.2, is-path-inside@npm:^3.0.3": + version: 3.0.3 + resolution: "is-path-inside@npm:3.0.3" + checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9 + languageName: node + linkType: hard + +"is-plain-obj@npm:^2.0.0, is-plain-obj@npm:^2.1.0": + version: 2.1.0 + resolution: "is-plain-obj@npm:2.1.0" + checksum: cec9100678b0a9fe0248a81743041ed990c2d4c99f893d935545cfbc42876cbe86d207f3b895700c690ad2fa520e568c44afc1605044b535a7820c1d40e38daa + languageName: node + linkType: hard + +"is-plain-obj@npm:^3.0.0": + version: 3.0.0 + resolution: "is-plain-obj@npm:3.0.0" + checksum: a6ebdf8e12ab73f33530641972a72a4b8aed6df04f762070d823808303e4f76d87d5ea5bd76f96a7bbe83d93f04ac7764429c29413bd9049853a69cb630fb21c + languageName: node + linkType: hard + +"is-plain-obj@npm:^4.0.0": + version: 4.1.0 + resolution: "is-plain-obj@npm:4.1.0" + checksum: 6dc45da70d04a81f35c9310971e78a6a3c7a63547ef782e3a07ee3674695081b6ca4e977fbb8efc48dae3375e0b34558d2bcd722aec9bddfa2d7db5b041be8ce + languageName: node + linkType: hard + +"is-plain-object@npm:^2.0.4": + version: 2.0.4 + resolution: "is-plain-object@npm:2.0.4" + dependencies: + isobject: ^3.0.1 + checksum: 2a401140cfd86cabe25214956ae2cfee6fbd8186809555cd0e84574f88de7b17abacb2e477a6a658fa54c6083ecbda1e6ae404c7720244cd198903848fca70ca + languageName: node + linkType: hard + +"is-plain-object@npm:^5.0.0": + version: 5.0.0 + resolution: "is-plain-object@npm:5.0.0" + checksum: e32d27061eef62c0847d303125440a38660517e586f2f3db7c9d179ae5b6674ab0f469d519b2e25c147a1a3bc87156d0d5f4d8821e0ce4a9ee7fe1fcf11ce45c + languageName: node + linkType: hard + +"is-port-reachable@npm:4.0.0": + version: 4.0.0 + resolution: "is-port-reachable@npm:4.0.0" + checksum: 47b7e10db8edcef27fbf9e50f0de85ad368d35688790ca64a13db67260111ac5f4b98989b11af06199fa93f25d810bd09a5b21b2c2646529668638f7c34d3c04 + languageName: node + linkType: hard + +"is-reference@npm:^3.0.0": + version: 3.0.2 + resolution: "is-reference@npm:3.0.2" + dependencies: + "@types/estree": "*" + checksum: ac3bf5626fe9d0afbd7454760d73c47f16b9f471401b9749721ad3b66f0a39644390382acf88ca9d029c95782c1e2ec65662855e3ba91acf52d82231247a7fd3 + languageName: node + linkType: hard + +"is-regexp@npm:^1.0.0": + version: 1.0.0 + resolution: "is-regexp@npm:1.0.0" + checksum: be692828e24cba479ec33644326fa98959ec68ba77965e0291088c1a741feaea4919d79f8031708f85fd25e39de002b4520622b55460660b9c369e6f7187faef + languageName: node + linkType: hard + +"is-root@npm:^2.1.0": + version: 2.1.0 + resolution: "is-root@npm:2.1.0" + checksum: 37eea0822a2a9123feb58a9d101558ba276771a6d830f87005683349a9acff15958a9ca590a44e778c6b335660b83e85c744789080d734f6081a935a4880aee2 + languageName: node + linkType: hard + +"is-stream@npm:^2.0.0": + version: 2.0.1 + resolution: "is-stream@npm:2.0.1" + checksum: b8e05ccdf96ac330ea83c12450304d4a591f9958c11fd17bed240af8d5ffe08aedafa4c0f4cfccd4d28dc9d4d129daca1023633d5c11601a6cbc77521f6fae66 + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.3": + version: 1.1.12 + resolution: "is-typed-array@npm:1.1.12" + dependencies: + which-typed-array: ^1.1.11 + checksum: 4c89c4a3be07186caddadf92197b17fda663a9d259ea0d44a85f171558270d36059d1c386d34a12cba22dfade5aba497ce22778e866adc9406098c8fc4771796 + languageName: node + linkType: hard + +"is-typedarray@npm:^1.0.0": + version: 1.0.0 + resolution: "is-typedarray@npm:1.0.0" + checksum: 3508c6cd0a9ee2e0df2fa2e9baabcdc89e911c7bd5cf64604586697212feec525aa21050e48affb5ffc3df20f0f5d2e2cf79b08caa64e1ccc9578e251763aef7 + languageName: node + linkType: hard + +"is-unicode-supported@npm:^0.1.0": + version: 0.1.0 + resolution: "is-unicode-supported@npm:0.1.0" + checksum: a2aab86ee7712f5c2f999180daaba5f361bdad1efadc9610ff5b8ab5495b86e4f627839d085c6530363c6d6d4ecbde340fb8e54bdb83da4ba8e0865ed5513c52 + languageName: node + linkType: hard + +"is-whitespace-character@npm:^1.0.0": + version: 1.0.4 + resolution: "is-whitespace-character@npm:1.0.4" + checksum: adab8ad9847ccfcb6f1b7000b8f622881b5ba2a09ce8be2794a6d2b10c3af325b469fc562c9fb889f468eed27be06e227ac609d0aa1e3a59b4dbcc88e2b0418e + languageName: node + linkType: hard + +"is-word-character@npm:^1.0.0": + version: 1.0.4 + resolution: "is-word-character@npm:1.0.4" + checksum: 1821d6c6abe5bc0b3abe3fdc565d66d7c8a74ea4e93bc77b4a47d26e2e2a306d6ab7d92b353b0d2b182869e3ecaa8f4a346c62d0e31d38ebc0ceaf7cae182c3f + languageName: node + linkType: hard + +"is-wsl@npm:^2.2.0": + version: 2.2.0 + resolution: "is-wsl@npm:2.2.0" + dependencies: + is-docker: ^2.0.0 + checksum: 20849846ae414997d290b75e16868e5261e86ff5047f104027026fd61d8b5a9b0b3ade16239f35e1a067b3c7cc02f70183cb661010ed16f4b6c7c93dad1b19d8 + languageName: node + linkType: hard + +"is-wsl@npm:^3.1.0": + version: 3.1.0 + resolution: "is-wsl@npm:3.1.0" + dependencies: + is-inside-container: ^1.0.0 + checksum: f9734c81f2f9cf9877c5db8356bfe1ff61680f1f4c1011e91278a9c0564b395ae796addb4bf33956871041476ec82c3e5260ed57b22ac91794d4ae70a1d2f0a9 + languageName: node + linkType: hard + +"is-yarn-global@npm:^0.3.0": + version: 0.3.0 + resolution: "is-yarn-global@npm:0.3.0" + checksum: bca013d65fee2862024c9fbb3ba13720ffca2fe750095174c1c80922fdda16402b5c233f5ac9e265bc12ecb5446e7b7f519a32d9541788f01d4d44e24d2bf481 + languageName: node + linkType: hard + +"is-yarn-global@npm:^0.4.0": + version: 0.4.1 + resolution: "is-yarn-global@npm:0.4.1" + checksum: 79ec4e6f581c53d4fefdf5f6c237f9a3ad8db29c85cdc4659e76ae345659317552052a97b7e56952aa5d94a23c798ebec8ccad72fb14d3b26dc647ddceddd716 + languageName: node + linkType: hard + +"is@npm:~0.2.6": + version: 0.2.7 + resolution: "is@npm:0.2.7" + checksum: 45cea1e6deb41150b5753e18041a833657313e9c791c73f96fb9014b613346f5af2e6650858ef50ea6262c79555b65e09b13d30a268139863885025dd65f1059 + languageName: node + linkType: hard + +"isarray@npm:0.0.1": + version: 0.0.1 + resolution: "isarray@npm:0.0.1" + checksum: 49191f1425681df4a18c2f0f93db3adb85573bcdd6a4482539d98eac9e705d8961317b01175627e860516a2fc45f8f9302db26e5a380a97a520e272e2a40a8d4 + languageName: node + linkType: hard + +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab + languageName: node + linkType: hard + +"isbinaryfile@npm:^5.0.0": + version: 5.0.0 + resolution: "isbinaryfile@npm:5.0.0" + checksum: 25cc27388d51b8322c103f5894f9e72ec04e017734e57c4b70be2666501ec7e7f6cbb4a5fcfd15260a7cac979bd1ddb7f5231f5a3098c0695c4e7c049513dfaf + languageName: node + linkType: hard + +"isbuffer@npm:~0.0.0": + version: 0.0.0 + resolution: "isbuffer@npm:0.0.0" + checksum: 9796296d3c493974c1f71ccf3170cc8007217a19ce8b3b9dedffd32e8ccc3ac42473b572bbf1b24b86143e826ea157aead11fd1285389518abab76c7da5f50ed + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + +"isobject@npm:^3.0.1": + version: 3.0.1 + resolution: "isobject@npm:3.0.1" + checksum: db85c4c970ce30693676487cca0e61da2ca34e8d4967c2e1309143ff910c207133a969f9e4ddb2dc6aba670aabce4e0e307146c310350b298e74a31f7d464703 + languageName: node + linkType: hard + +"istanbul-lib-coverage@npm:^3.0.0": + version: 3.2.2 + resolution: "istanbul-lib-coverage@npm:3.2.2" + checksum: 2367407a8d13982d8f7a859a35e7f8dd5d8f75aae4bb5484ede3a9ea1b426dc245aff28b976a2af48ee759fdd9be374ce2bd2669b644f31e76c5f46a2e29a831 + languageName: node + linkType: hard + +"istanbul-lib-report@npm:^3.0.0, istanbul-lib-report@npm:^3.0.1": + version: 3.0.1 + resolution: "istanbul-lib-report@npm:3.0.1" + dependencies: + istanbul-lib-coverage: ^3.0.0 + make-dir: ^4.0.0 + supports-color: ^7.1.0 + checksum: fd17a1b879e7faf9bb1dc8f80b2a16e9f5b7b8498fe6ed580a618c34df0bfe53d2abd35bf8a0a00e628fb7405462576427c7df20bbe4148d19c14b431c974b21 + languageName: node + linkType: hard + +"istanbul-reports@npm:^3.0.2": + version: 3.1.6 + resolution: "istanbul-reports@npm:3.1.6" + dependencies: + html-escaper: ^2.0.0 + istanbul-lib-report: ^3.0.0 + checksum: 44c4c0582f287f02341e9720997f9e82c071627e1e862895745d5f52ec72c9b9f38e1d12370015d2a71dcead794f34c7732aaef3fab80a24bc617a21c3d911d6 + languageName: node + linkType: hard + +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 57d43ad11eadc98cdfe7496612f6bbb5255ea69fe51ea431162db302c2a11011642f50cfad57288bd0aea78384a0612b16e131944ad8ecd09d619041c8531b54 + languageName: node + linkType: hard + +"jest-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-util@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: 042ab4980f4ccd4d50226e01e5c7376a8556b472442ca6091a8f102488c0f22e6e8b89ea874111d2328a2080083bf3225c86f3788c52af0bd0345a00eb57a3ca + languageName: node + linkType: hard + +"jest-worker@npm:^27.4.5": + version: 27.5.1 + resolution: "jest-worker@npm:27.5.1" + dependencies: + "@types/node": "*" + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 98cd68b696781caed61c983a3ee30bf880b5bd021c01d98f47b143d4362b85d0737f8523761e2713d45e18b4f9a2b98af1eaee77afade4111bb65c77d6f7c980 + languageName: node + linkType: hard + +"jest-worker@npm:^29.1.2, jest-worker@npm:^29.4.3": + version: 29.7.0 + resolution: "jest-worker@npm:29.7.0" + dependencies: + "@types/node": "*" + jest-util: ^29.7.0 + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 30fff60af49675273644d408b650fc2eb4b5dcafc5a0a455f238322a8f9d8a98d847baca9d51ff197b6747f54c7901daa2287799230b856a0f48287d131f8c13 + languageName: node + linkType: hard + +"jiti@npm:^1.18.2, jiti@npm:^1.20.0": + version: 1.21.0 + resolution: "jiti@npm:1.21.0" + bin: + jiti: bin/jiti.js + checksum: a7bd5d63921c170eaec91eecd686388181c7828e1fa0657ab374b9372bfc1f383cf4b039e6b272383d5cb25607509880af814a39abdff967322459cca41f2961 + languageName: node + linkType: hard + +"joi@npm:^17.6.0, joi@npm:^17.9.2": + version: 17.11.0 + resolution: "joi@npm:17.11.0" + dependencies: + "@hapi/hoek": ^9.0.0 + "@hapi/topo": ^5.0.0 + "@sideway/address": ^4.1.3 + "@sideway/formula": ^3.0.1 + "@sideway/pinpoint": ^2.0.0 + checksum: 3a4e9ecba345cdafe585e7ed8270a44b39718e11dff3749aa27e0001a63d578b75100c062be28e6f48f960b594864034e7a13833f33fbd7ad56d5ce6b617f9bf + languageName: node + linkType: hard + +"js-sha3@npm:0.8.0": + version: 0.8.0 + resolution: "js-sha3@npm:0.8.0" + checksum: 75df77c1fc266973f06cce8309ce010e9e9f07ec35ab12022ed29b7f0d9c8757f5a73e1b35aa24840dced0dea7059085aa143d817aea9e188e2a80d569d9adce + languageName: node + linkType: hard + +"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": + version: 4.0.0 + resolution: "js-tokens@npm:4.0.0" + checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 + languageName: node + linkType: hard + +"js-yaml@npm:4.1.0, js-yaml@npm:^4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" + dependencies: + argparse: ^2.0.1 + bin: + js-yaml: bin/js-yaml.js + checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a + languageName: node + linkType: hard + +"js-yaml@npm:^3.13.1": + version: 3.14.1 + resolution: "js-yaml@npm:3.14.1" + dependencies: + argparse: ^1.0.7 + esprima: ^4.0.0 + bin: + js-yaml: bin/js-yaml.js + checksum: bef146085f472d44dee30ec34e5cf36bf89164f5d585435a3d3da89e52622dff0b188a580e4ad091c3341889e14cb88cac6e4deb16dc5b1e9623bb0601fc255c + languageName: node + linkType: hard + +"jsesc@npm:^2.5.1": + version: 2.5.2 + resolution: "jsesc@npm:2.5.2" + bin: + jsesc: bin/jsesc + checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d + languageName: node + linkType: hard + +"jsesc@npm:~0.5.0": + version: 0.5.0 + resolution: "jsesc@npm:0.5.0" + bin: + jsesc: bin/jsesc + checksum: b8b44cbfc92f198ad972fba706ee6a1dfa7485321ee8c0b25f5cedd538dcb20cde3197de16a7265430fce8277a12db066219369e3d51055038946039f6e20e17 + languageName: node + linkType: hard + +"json-buffer@npm:3.0.0": + version: 3.0.0 + resolution: "json-buffer@npm:3.0.0" + checksum: 0cecacb8025370686a916069a2ff81f7d55167421b6aa7270ee74e244012650dd6bce22b0852202ea7ff8624fce50ff0ec1bdf95914ccb4553426e290d5a63fa + languageName: node + linkType: hard + +"json-buffer@npm:3.0.1": + version: 3.0.1 + resolution: "json-buffer@npm:3.0.1" + checksum: 9026b03edc2847eefa2e37646c579300a1f3a4586cfb62bf857832b60c852042d0d6ae55d1afb8926163fa54c2b01d83ae24705f34990348bdac6273a29d4581 + languageName: node + linkType: hard + +"json-joy@npm:^9.2.0": + version: 9.9.1 + resolution: "json-joy@npm:9.9.1" + dependencies: + arg: ^5.0.2 + hyperdyperid: ^1.2.0 + peerDependencies: + quill-delta: ^5 + rxjs: 7 + tslib: 2 + bin: + jj: bin/jj.js + json-pack: bin/json-pack.js + json-pack-test: bin/json-pack-test.js + json-patch: bin/json-patch.js + json-patch-test: bin/json-patch-test.js + json-pointer: bin/json-pointer.js + json-pointer-test: bin/json-pointer-test.js + json-unpack: bin/json-unpack.js + checksum: d165398682f00019796225faf365cd8d060f3e086af39bb5081c30907b7e52eaf13697d1c0f6ee2b010fe255ae1fd776e05ad7d6ee5fb549e98fe982f560884b + languageName: node + linkType: hard + +"json-parse-even-better-errors@npm:^2.3.0, json-parse-even-better-errors@npm:^2.3.1": + version: 2.3.1 + resolution: "json-parse-even-better-errors@npm:2.3.1" + checksum: 798ed4cf3354a2d9ccd78e86d2169515a0097a5c133337807cdf7f1fc32e1391d207ccfc276518cc1d7d8d4db93288b8a50ba4293d212ad1336e52a8ec0a941f + languageName: node + linkType: hard + +"json-schema-traverse@npm:^0.4.1": + version: 0.4.1 + resolution: "json-schema-traverse@npm:0.4.1" + checksum: 7486074d3ba247769fda17d5181b345c9fb7d12e0da98b22d1d71a5db9698d8b4bd900a3ec1a4ffdd60846fc2556274a5c894d0c48795f14cb03aeae7b55260b + languageName: node + linkType: hard + +"json-schema-traverse@npm:^1.0.0": + version: 1.0.0 + resolution: "json-schema-traverse@npm:1.0.0" + checksum: 02f2f466cdb0362558b2f1fd5e15cce82ef55d60cd7f8fa828cf35ba74330f8d767fcae5c5c2adb7851fa811766c694b9405810879bc4e1ddd78a7c0e03658ad + languageName: node + linkType: hard + +"json-stable-stringify-without-jsonify@npm:^1.0.1": + version: 1.0.1 + resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" + checksum: cff44156ddce9c67c44386ad5cddf91925fe06b1d217f2da9c4910d01f358c6e3989c4d5a02683c7a5667f9727ff05831f7aa8ae66c8ff691c556f0884d49215 + languageName: node + linkType: hard + +"json5@npm:^2.1.2, json5@npm:^2.2.3": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 + languageName: node + linkType: hard + +"jsonc-parser@npm:^3.2.0": + version: 3.2.0 + resolution: "jsonc-parser@npm:3.2.0" + checksum: 946dd9a5f326b745aa326d48a7257e3f4a4b62c5e98ec8e49fa2bdd8d96cef7e6febf1399f5c7016114fd1f68a1c62c6138826d5d90bc650448e3cf0951c53c7 + languageName: node + linkType: hard + +"jsonfile@npm:^4.0.0": + version: 4.0.0 + resolution: "jsonfile@npm:4.0.0" + dependencies: + graceful-fs: ^4.1.6 + dependenciesMeta: + graceful-fs: + optional: true + checksum: 6447d6224f0d31623eef9b51185af03ac328a7553efcee30fa423d98a9e276ca08db87d71e17f2310b0263fd3ffa6c2a90a6308367f661dc21580f9469897c9e + languageName: node + linkType: hard + +"jsonfile@npm:^6.0.1": + version: 6.1.0 + resolution: "jsonfile@npm:6.1.0" + dependencies: + graceful-fs: ^4.1.6 + universalify: ^2.0.0 + dependenciesMeta: + graceful-fs: + optional: true + checksum: 7af3b8e1ac8fe7f1eccc6263c6ca14e1966fcbc74b618d3c78a0a2075579487547b94f72b7a1114e844a1e15bb00d440e5d1720bfc4612d790a6f285d5ea8354 + languageName: node + linkType: hard + +"just-extend@npm:^4.0.2": + version: 4.2.1 + resolution: "just-extend@npm:4.2.1" + checksum: ff9fdede240fad313efeeeb68a660b942e5586d99c0058064c78884894a2690dc09bba44c994ad4e077e45d913fef01a9240c14a72c657b53687ac58de53b39c + languageName: node + linkType: hard + +"katex@npm:^0.16.0": + version: 0.16.9 + resolution: "katex@npm:0.16.9" + dependencies: + commander: ^8.3.0 + bin: + katex: cli.js + checksum: 861194dfd4d86505e657f688fb73048d46ac498edafce71199502a35b03c0ecc35ba930c631be79c4a09d90a0d23476673cd52f6bc367c7a161854d64005fa95 + languageName: node + linkType: hard + +"keccak@npm:^3.0.0, keccak@npm:^3.0.2": + version: 3.0.4 + resolution: "keccak@npm:3.0.4" + dependencies: + node-addon-api: ^2.0.0 + node-gyp: latest + node-gyp-build: ^4.2.0 + readable-stream: ^3.6.0 + checksum: 2bf27b97b2f24225b1b44027de62be547f5c7326d87d249605665abd0c8c599d774671c35504c62c9b922cae02758504c6f76a73a84234d23af8a2211afaaa11 + languageName: node + linkType: hard + +"keygrip@npm:~1.1.0": + version: 1.1.0 + resolution: "keygrip@npm:1.1.0" + dependencies: + tsscmp: 1.0.6 + checksum: 078cd16a463d187121f0a27c1c9c95c52ad392b620f823431689f345a0501132cee60f6e96914b07d570105af470b96960402accd6c48a0b1f3cd8fac4fa2cae + languageName: node + linkType: hard + +"keyv@npm:^3.0.0": + version: 3.1.0 + resolution: "keyv@npm:3.1.0" + dependencies: + json-buffer: 3.0.0 + checksum: bb7e8f3acffdbafbc2dd5b63f377fe6ec4c0e2c44fc82720449ef8ab54f4a7ce3802671ed94c0f475ae0a8549703353a2124561fcf3317010c141b32ca1ce903 + languageName: node + linkType: hard + +"keyv@npm:^4.5.3, keyv@npm:^4.5.4": + version: 4.5.4 + resolution: "keyv@npm:4.5.4" + dependencies: + json-buffer: 3.0.1 + checksum: 74a24395b1c34bd44ad5cb2b49140d087553e170625240b86755a6604cd65aa16efdbdeae5cdb17ba1284a0fbb25ad06263755dbc71b8d8b06f74232ce3cdd72 + languageName: node + linkType: hard + +"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2": + version: 6.0.3 + resolution: "kind-of@npm:6.0.3" + checksum: 3ab01e7b1d440b22fe4c31f23d8d38b4d9b91d9f291df683476576493d5dfd2e03848a8b05813dd0c3f0e835bc63f433007ddeceb71f05cb25c45ae1b19c6d3b + languageName: node + linkType: hard + +"klaw-sync@npm:^6.0.0": + version: 6.0.0 + resolution: "klaw-sync@npm:6.0.0" + dependencies: + graceful-fs: ^4.1.11 + checksum: 0da397f8961313c3ef8f79fb63af9002cde5a8fb2aeb1a37351feff0dd6006129c790400c3f5c3b4e757bedcabb13d21ec0a5eaef5a593d59515d4f2c291e475 + languageName: node + linkType: hard + +"kleur@npm:^3.0.3": + version: 3.0.3 + resolution: "kleur@npm:3.0.3" + checksum: df82cd1e172f957bae9c536286265a5cdbd5eeca487cb0a3b2a7b41ef959fc61f8e7c0e9aeea9c114ccf2c166b6a8dd45a46fd619c1c569d210ecd2765ad5169 + languageName: node + linkType: hard + +"koa-compose@npm:^4.1.0": + version: 4.1.0 + resolution: "koa-compose@npm:4.1.0" + checksum: 46cb16792d96425e977c2ae4e5cb04930280740e907242ec9c25e3fb8b4a1d7b54451d7432bc24f40ec62255edea71894d2ceeb8238501842b4e48014f2e83db + languageName: node + linkType: hard + +"koa-convert@npm:^2.0.0": + version: 2.0.0 + resolution: "koa-convert@npm:2.0.0" + dependencies: + co: ^4.6.0 + koa-compose: ^4.1.0 + checksum: 7385b3391995f59c1312142e110d5dff677f9850dbfbcf387cd36a7b0af03b5d26e82b811eb9bb008b4f3e661cdab1f8817596e46b1929da2cf6e97a2f7456ed + languageName: node + linkType: hard + +"koa-etag@npm:^4.0.0": + version: 4.0.0 + resolution: "koa-etag@npm:4.0.0" + dependencies: + etag: ^1.8.1 + checksum: b5f413574e1edbd60fbbd0d31720e66565d51bfcb407d1bc3f48d9dd5b45fa5a9e4f69a60e749fad7397348e90de23e943307578d007a69da30faaae432deaf6 + languageName: node + linkType: hard + +"koa-send@npm:^5.0.0, koa-send@npm:^5.0.1": + version: 5.0.1 + resolution: "koa-send@npm:5.0.1" + dependencies: + debug: ^4.1.1 + http-errors: ^1.7.3 + resolve-path: ^1.4.0 + checksum: a9fbaadbe0f50efd157a733df4a1cc2b3b79b0cdf12e67c718641e6038d1792c0bebe40913e6d4ceb707d970301155be3859b98d1ef08b0fd1766f7326b82853 + languageName: node + linkType: hard + +"koa-static@npm:^5.0.0": + version: 5.0.0 + resolution: "koa-static@npm:5.0.0" + dependencies: + debug: ^3.1.0 + koa-send: ^5.0.0 + checksum: 8d9b9c4d2b3b13e8818e804245d784099c4b353b55ddd7dbeeb90f27a2e9f5b6f86bd16a4909e337cb89db4d332d9002e6c0f5056caf75749cab62f93c1f0cc5 + languageName: node + linkType: hard + +"koa@npm:^2.13.0": + version: 2.14.2 + resolution: "koa@npm:2.14.2" + dependencies: + accepts: ^1.3.5 + cache-content-type: ^1.0.0 + content-disposition: ~0.5.2 + content-type: ^1.0.4 + cookies: ~0.8.0 + debug: ^4.3.2 + delegates: ^1.0.0 + depd: ^2.0.0 + destroy: ^1.0.4 + encodeurl: ^1.0.2 + escape-html: ^1.0.3 + fresh: ~0.5.2 + http-assert: ^1.3.0 + http-errors: ^1.6.3 + is-generator-function: ^1.0.7 + koa-compose: ^4.1.0 + koa-convert: ^2.0.0 + on-finished: ^2.3.0 + only: ~0.0.2 + parseurl: ^1.3.2 + statuses: ^1.5.0 + type-is: ^1.6.16 + vary: ^1.1.2 + checksum: 17fe3b8f5e0b4759004a942cc6ba2a9507299943a697dff9766b85f41f45caed4077ca2645ac9ad254d3359fffedfc4c9ebdd7a70493e5df8cdfac159a8ee835 + languageName: node + linkType: hard + +"latest-version@npm:^5.1.0": + version: 5.1.0 + resolution: "latest-version@npm:5.1.0" + dependencies: + package-json: ^6.3.0 + checksum: fbc72b071eb66c40f652441fd783a9cca62f08bf42433651937f078cd9ef94bf728ec7743992777826e4e89305aef24f234b515e6030503a2cbee7fc9bdc2c0f + languageName: node + linkType: hard + +"latest-version@npm:^7.0.0": + version: 7.0.0 + resolution: "latest-version@npm:7.0.0" + dependencies: + package-json: ^8.1.0 + checksum: 1f0deba00d5a34394cce4463c938811f51bbb539b131674f4bb2062c63f2cc3b80bccd56ecade3bd5932d04a34cf0a5a8a2ccc4ec9e5e6b285a9a7b3e27d0d66 + languageName: node + linkType: hard + +"launch-editor@npm:^2.6.0, launch-editor@npm:^2.6.1": + version: 2.6.1 + resolution: "launch-editor@npm:2.6.1" + dependencies: + picocolors: ^1.0.0 + shell-quote: ^1.8.1 + checksum: e06d193075ac09f7f8109f10cabe464a211bf7ed4cbe75f83348d6f67bf4d9f162f06e7a1ab3e1cd7fc250b5342c3b57080618aff2e646dc34248fe499227601 + languageName: node + linkType: hard + +"level-blobs@npm:^0.1.7": + version: 0.1.7 + resolution: "level-blobs@npm:0.1.7" + dependencies: + level-peek: 1.0.6 + once: ^1.3.0 + readable-stream: ^1.0.26-4 + checksum: e3cf78ef0bc64ff350edb4e247b2689cd4f5facf1119694ca8c96c28a05a38dc9d88e0bd065b18af65330bc22f5d588719a5c3e63adaa5feba5ea7913f87bebe + languageName: node + linkType: hard + +"level-filesystem@npm:^1.0.1": + version: 1.2.0 + resolution: "level-filesystem@npm:1.2.0" + dependencies: + concat-stream: ^1.4.4 + errno: ^0.1.1 + fwd-stream: ^1.0.4 + level-blobs: ^0.1.7 + level-peek: ^1.0.6 + level-sublevel: ^5.2.0 + octal: ^1.0.0 + once: ^1.3.0 + xtend: ^2.2.0 + checksum: a29e6a9d8c1879d43610113d1bcb59368685ec0ae413fcf0f8dcbb0a0c26b88fcf16f7481acb2b4650e5951ba0635e73a2c8fbe25cd599c50f80949a5547a367 + languageName: node + linkType: hard + +"level-fix-range@npm:2.0": + version: 2.0.0 + resolution: "level-fix-range@npm:2.0.0" + dependencies: + clone: ~0.1.9 + checksum: 250cefa69e1035d1412b4ba3e5cab83cceb894aa833fb0a93417d8d6230c60f6f8154feffbd0f116461ddd441b909e7df1323355d3e1769b3bb20a55729145b5 + languageName: node + linkType: hard + +"level-fix-range@npm:~1.0.2": + version: 1.0.2 + resolution: "level-fix-range@npm:1.0.2" + checksum: 6c9a3894ea08947fae79c41b75e8b9d57979523b656bec43c589f2dc4455276a150df445d9a7ca880a7c58c2ef19f5cea7f661d777993b870f4943af6b31d5bb + languageName: node + linkType: hard + +"level-hooks@npm:>=4.4.0 <5": + version: 4.5.0 + resolution: "level-hooks@npm:4.5.0" + dependencies: + string-range: ~1.2 + checksum: f198ad2e0901a4719e324e67f546097589af79665ebaaabee7122fda18a41ada3158bb1816b8b82430f30c68610125e4e20b5c09ec3ba7ae262d97dba34f48ab + languageName: node + linkType: hard + +"level-js@npm:^2.1.3": + version: 2.2.4 + resolution: "level-js@npm:2.2.4" + dependencies: + abstract-leveldown: ~0.12.0 + idb-wrapper: ^1.5.0 + isbuffer: ~0.0.0 + ltgt: ^2.1.2 + typedarray-to-buffer: ~1.0.0 + xtend: ~2.1.2 + checksum: 4fed784fcfad4bc6ec97d9c3897e95eaa30326fcdab9f4c7437624d10fa875fa84aafcc2acac0d53181af506cbc012c03f413b4da12ff83758d3bcbb699f8c8e + languageName: node + linkType: hard + +"level-peek@npm:1.0.6, level-peek@npm:^1.0.6": + version: 1.0.6 + resolution: "level-peek@npm:1.0.6" + dependencies: + level-fix-range: ~1.0.2 + checksum: e07d5f8b80675727204d9a226a249139da9e354e633b9d57b7a5186a7b85be445e550ca628f5133bf7a220a9311a193ded5a3f83588dc4eaa53ffb86b426154a + languageName: node + linkType: hard + +"level-sublevel@npm:^5.2.0": + version: 5.2.3 + resolution: "level-sublevel@npm:5.2.3" + dependencies: + level-fix-range: 2.0 + level-hooks: ">=4.4.0 <5" + string-range: ~1.2.1 + xtend: ~2.0.4 + checksum: f0fdffc2f9ca289aa183a1bf7f300a8f92e4f01be60eab37ab36e1f6ec33ed449519d8f69504a616e82f3ddca13a15fa4e19af1dcc1beba9044a4c60b6cd94bf + languageName: node + linkType: hard + +"levelup@npm:^0.18.2": + version: 0.18.6 + resolution: "levelup@npm:0.18.6" + dependencies: + bl: ~0.8.1 + deferred-leveldown: ~0.2.0 + errno: ~0.1.1 + prr: ~0.0.0 + readable-stream: ~1.0.26 + semver: ~2.3.1 + xtend: ~3.0.0 + checksum: 80e140dd83dc94050e283fc02874ae85116cb560d81e14fee0ac111f86006887835ec905dca7a081414c07eca202245a580f1e02f696367b777ecc23a9e05b86 + languageName: node + linkType: hard + +"leven@npm:^3.1.0": + version: 3.1.0 + resolution: "leven@npm:3.1.0" + checksum: 638401d534585261b6003db9d99afd244dfe82d75ddb6db5c0df412842d5ab30b2ef18de471aaec70fe69a46f17b4ae3c7f01d8a4e6580ef7adb9f4273ad1e55 + languageName: node + linkType: hard + +"levn@npm:^0.4.1": + version: 0.4.1 + resolution: "levn@npm:0.4.1" + dependencies: + prelude-ls: ^1.2.1 + type-check: ~0.4.0 + checksum: 12c5021c859bd0f5248561bf139121f0358285ec545ebf48bb3d346820d5c61a4309535c7f387ed7d84361cf821e124ce346c6b7cef8ee09a67c1473b46d0fc4 + languageName: node + linkType: hard + +"lighthouse-logger@npm:^1.0.0": + version: 1.4.2 + resolution: "lighthouse-logger@npm:1.4.2" + dependencies: + debug: ^2.6.9 + marky: ^1.2.2 + checksum: ba6b73d93424318fab58b4e07c9ed246e3e969a3313f26b69515ed4c06457dd9a0b11bc706948398fdaef26aa4ba5e65cb848c37ce59f470d3c6c450b9b79a33 + languageName: node + linkType: hard + +"lilconfig@npm:^2.0.3": + version: 2.1.0 + resolution: "lilconfig@npm:2.1.0" + checksum: 8549bb352b8192375fed4a74694cd61ad293904eee33f9d4866c2192865c44c4eb35d10782966242634e0cbc1e91fe62b1247f148dc5514918e3a966da7ea117 + languageName: node + linkType: hard + +"lilconfig@npm:^3.1.1": + version: 3.1.2 + resolution: "lilconfig@npm:3.1.2" + checksum: 4e8b83ddd1d0ad722600994e6ba5d858ddca14f0587aa6b9c8185e17548149b5e13d4d583d811e9e9323157fa8c6a527e827739794c7502b59243c58e210b8c3 + languageName: node + linkType: hard + +"lines-and-columns@npm:^1.1.6": + version: 1.2.4 + resolution: "lines-and-columns@npm:1.2.4" + checksum: 0c37f9f7fa212b38912b7145e1cd16a5f3cd34d782441c3e6ca653485d326f58b3caccda66efce1c5812bde4961bbde3374fae4b0d11bf1226152337f3894aa5 + languageName: node + linkType: hard + +"loader-runner@npm:^4.2.0": + version: 4.3.0 + resolution: "loader-runner@npm:4.3.0" + checksum: a90e00dee9a16be118ea43fec3192d0b491fe03a32ed48a4132eb61d498f5536a03a1315531c19d284392a8726a4ecad71d82044c28d7f22ef62e029bf761569 + languageName: node + linkType: hard + +"loader-utils@npm:^2.0.0": + version: 2.0.4 + resolution: "loader-utils@npm:2.0.4" + dependencies: + big.js: ^5.2.2 + emojis-list: ^3.0.0 + json5: ^2.1.2 + checksum: a5281f5fff1eaa310ad5e1164095689443630f3411e927f95031ab4fb83b4a98f388185bb1fe949e8ab8d4247004336a625e9255c22122b815bb9a4c5d8fc3b7 + languageName: node + linkType: hard + +"loader-utils@npm:^3.2.0": + version: 3.2.1 + resolution: "loader-utils@npm:3.2.1" + checksum: 4e3ea054cdc8be1ab1f1238f49f42fdf0483039eff920fb1d442039f3f0ad4ebd11fb8e584ccdf2cb7e3c56b3d40c1832416e6408a55651b843da288960cc792 + languageName: node + linkType: hard + +"locate-path@npm:^2.0.0": + version: 2.0.0 + resolution: "locate-path@npm:2.0.0" + dependencies: + p-locate: ^2.0.0 + path-exists: ^3.0.0 + checksum: 02d581edbbbb0fa292e28d96b7de36b5b62c2fa8b5a7e82638ebb33afa74284acf022d3b1e9ae10e3ffb7658fbc49163fcd5e76e7d1baaa7801c3e05a81da755 + languageName: node + linkType: hard + +"locate-path@npm:^3.0.0": + version: 3.0.0 + resolution: "locate-path@npm:3.0.0" + dependencies: + p-locate: ^3.0.0 + path-exists: ^3.0.0 + checksum: 53db3996672f21f8b0bf2a2c645ae2c13ffdae1eeecfcd399a583bce8516c0b88dcb4222ca6efbbbeb6949df7e46860895be2c02e8d3219abd373ace3bfb4e11 + languageName: node + linkType: hard + +"locate-path@npm:^5.0.0": + version: 5.0.0 + resolution: "locate-path@npm:5.0.0" + dependencies: + p-locate: ^4.1.0 + checksum: 83e51725e67517287d73e1ded92b28602e3ae5580b301fe54bfb76c0c723e3f285b19252e375712316774cf52006cb236aed5704692c32db0d5d089b69696e30 + languageName: node + linkType: hard + +"locate-path@npm:^6.0.0": + version: 6.0.0 + resolution: "locate-path@npm:6.0.0" + dependencies: + p-locate: ^5.0.0 + checksum: 72eb661788a0368c099a184c59d2fee760b3831c9c1c33955e8a19ae4a21b4116e53fa736dc086cdeb9fce9f7cc508f2f92d2d3aae516f133e16a2bb59a39f5a + languageName: node + linkType: hard + +"locate-path@npm:^7.1.0": + version: 7.2.0 + resolution: "locate-path@npm:7.2.0" + dependencies: + p-locate: ^6.0.0 + checksum: c1b653bdf29beaecb3d307dfb7c44d98a2a98a02ebe353c9ad055d1ac45d6ed4e1142563d222df9b9efebc2bcb7d4c792b507fad9e7150a04c29530b7db570f8 + languageName: node + linkType: hard + +"lodash.assignwith@npm:^4.2.0": + version: 4.2.0 + resolution: "lodash.assignwith@npm:4.2.0" + checksum: 014a88e398802ca4eaae314afb67f32eb2cab6f01e61490dbbb74694263f79715341ab8ddf4b344093a2253b506d347f67731f0499e457d9c0128be1d2caf6dd + languageName: node + linkType: hard + +"lodash.camelcase@npm:^4.3.0": + version: 4.3.0 + resolution: "lodash.camelcase@npm:4.3.0" + checksum: cb9227612f71b83e42de93eccf1232feeb25e705bdb19ba26c04f91e885bfd3dd5c517c4a97137658190581d3493ea3973072ca010aab7e301046d90740393d1 + languageName: node + linkType: hard + +"lodash.debounce@npm:^4.0.8": + version: 4.0.8 + resolution: "lodash.debounce@npm:4.0.8" + checksum: a3f527d22c548f43ae31c861ada88b2637eb48ac6aa3eb56e82d44917971b8aa96fbb37aa60efea674dc4ee8c42074f90f7b1f772e9db375435f6c83a19b3bc6 + languageName: node + linkType: hard + +"lodash.get@npm:^4.4.2": + version: 4.4.2 + resolution: "lodash.get@npm:4.4.2" + checksum: e403047ddb03181c9d0e92df9556570e2b67e0f0a930fcbbbd779370972368f5568e914f913e93f3b08f6d492abc71e14d4e9b7a18916c31fa04bd2306efe545 + languageName: node + linkType: hard + +"lodash.isequal@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.isequal@npm:4.5.0" + checksum: da27515dc5230eb1140ba65ff8de3613649620e8656b19a6270afe4866b7bd461d9ba2ac8a48dcc57f7adac4ee80e1de9f965d89d4d81a0ad52bb3eec2609644 + languageName: node + linkType: hard + +"lodash.memoize@npm:^4.1.2": + version: 4.1.2 + resolution: "lodash.memoize@npm:4.1.2" + checksum: 9ff3942feeccffa4f1fafa88d32f0d24fdc62fd15ded5a74a5f950ff5f0c6f61916157246744c620173dddf38d37095a92327d5fd3861e2063e736a5c207d089 + languageName: node + linkType: hard + +"lodash.merge@npm:^4.6.2": + version: 4.6.2 + resolution: "lodash.merge@npm:4.6.2" + checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 + languageName: node + linkType: hard + +"lodash.uniq@npm:4.5.0, lodash.uniq@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.uniq@npm:4.5.0" + checksum: a4779b57a8d0f3c441af13d9afe7ecff22dd1b8ce1129849f71d9bbc8e8ee4e46dfb4b7c28f7ad3d67481edd6e51126e4e2a6ee276e25906d10f7140187c392d + languageName: node + linkType: hard + +"lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 + languageName: node + linkType: hard + +"log-symbols@npm:4.1.0": + version: 4.1.0 + resolution: "log-symbols@npm:4.1.0" + dependencies: + chalk: ^4.1.0 + is-unicode-supported: ^0.1.0 + checksum: fce1497b3135a0198803f9f07464165e9eb83ed02ceb2273930a6f8a508951178d8cf4f0378e9d28300a2ed2bc49050995d2bd5f53ab716bb15ac84d58c6ef74 + languageName: node + linkType: hard + +"log-update@npm:^4.0.0": + version: 4.0.0 + resolution: "log-update@npm:4.0.0" + dependencies: + ansi-escapes: ^4.3.0 + cli-cursor: ^3.1.0 + slice-ansi: ^4.0.0 + wrap-ansi: ^6.2.0 + checksum: ae2f85bbabc1906034154fb7d4c4477c79b3e703d22d78adee8b3862fa913942772e7fa11713e3d96fb46de4e3cabefbf5d0a544344f03b58d3c4bff52aa9eb2 + languageName: node + linkType: hard + +"longest-streak@npm:^3.0.0": + version: 3.1.0 + resolution: "longest-streak@npm:3.1.0" + checksum: d7f952ed004cbdb5c8bcfc4f7f5c3d65449e6c5a9e9be4505a656e3df5a57ee125f284286b4bf8ecea0c21a7b3bf2b8f9001ad506c319b9815ad6a63a47d0fd0 + languageName: node + linkType: hard + +"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.2.0, loose-envify@npm:^1.3.1, loose-envify@npm:^1.4.0": + version: 1.4.0 + resolution: "loose-envify@npm:1.4.0" + dependencies: + js-tokens: ^3.0.0 || ^4.0.0 + bin: + loose-envify: cli.js + checksum: 6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4 + languageName: node + linkType: hard + +"loupe@npm:^2.3.6": + version: 2.3.7 + resolution: "loupe@npm:2.3.7" + dependencies: + get-func-name: ^2.0.1 + checksum: 96c058ec7167598e238bb7fb9def2f9339215e97d6685d9c1e3e4bdb33d14600e11fe7a812cf0c003dfb73ca2df374f146280b2287cae9e8d989e9d7a69a203b + languageName: node + linkType: hard + +"lower-case@npm:^2.0.2": + version: 2.0.2 + resolution: "lower-case@npm:2.0.2" + dependencies: + tslib: ^2.0.3 + checksum: 83a0a5f159ad7614bee8bf976b96275f3954335a84fad2696927f609ddae902802c4f3312d86668722e668bef41400254807e1d3a7f2e8c3eede79691aa1f010 + languageName: node + linkType: hard + +"lowercase-keys@npm:^1.0.0, lowercase-keys@npm:^1.0.1": + version: 1.0.1 + resolution: "lowercase-keys@npm:1.0.1" + checksum: 4d045026595936e09953e3867722e309415ff2c80d7701d067546d75ef698dac218a4f53c6d1d0e7368b47e45fd7529df47e6cb56fbb90523ba599f898b3d147 + languageName: node + linkType: hard + +"lowercase-keys@npm:^2.0.0": + version: 2.0.0 + resolution: "lowercase-keys@npm:2.0.0" + checksum: 24d7ebd56ccdf15ff529ca9e08863f3c54b0b9d1edb97a3ae1af34940ae666c01a1e6d200707bce730a8ef76cb57cc10e65f245ecaaf7e6bc8639f2fb460ac23 + languageName: node + linkType: hard + +"lowercase-keys@npm:^3.0.0": + version: 3.0.0 + resolution: "lowercase-keys@npm:3.0.0" + checksum: 67a3f81409af969bc0c4ca0e76cd7d16adb1e25aa1c197229587eaf8671275c8c067cd421795dbca4c81be0098e4c426a086a05e30de8a9c587b7a13c0c7ccc5 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.1.0 + resolution: "lru-cache@npm:10.1.0" + checksum: 58056d33e2500fbedce92f8c542e7c11b50d7d086578f14b7074d8c241422004af0718e08a6eaae8705cee09c77e39a61c1c79e9370ba689b7010c152e6a76ab + languageName: node + linkType: hard + +"lru-cache@npm:^5.1.1": + version: 5.1.1 + resolution: "lru-cache@npm:5.1.1" + dependencies: + yallist: ^3.0.2 + checksum: c154ae1cbb0c2206d1501a0e94df349653c92c8cbb25236d7e85190bcaf4567a03ac6eb43166fabfa36fd35623694da7233e88d9601fbf411a9a481d85dbd2cb + languageName: node + linkType: hard + +"lru-cache@npm:^6.0.0": + version: 6.0.0 + resolution: "lru-cache@npm:6.0.0" + dependencies: + yallist: ^4.0.0 + checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 + languageName: node + linkType: hard + +"lru-cache@npm:^7.14.1": + version: 7.18.3 + resolution: "lru-cache@npm:7.18.3" + checksum: e550d772384709deea3f141af34b6d4fa392e2e418c1498c078de0ee63670f1f46f5eee746e8ef7e69e1c895af0d4224e62ee33e66a543a14763b0f2e74c1356 + languageName: node + linkType: hard + +"lru-cache@npm:^8.0.4": + version: 8.0.5 + resolution: "lru-cache@npm:8.0.5" + checksum: 87d72196d8f46e8299c4ab576ed2ec8a07e3cbef517dc9874399c0b2470bd9bf62aacec3b67f84ed6d74aaa1ef31636d048edf996f76248fd17db72bfb631609 + languageName: node + linkType: hard + +"lru_map@npm:^0.3.3": + version: 0.3.3 + resolution: "lru_map@npm:0.3.3" + checksum: ca9dd43c65ed7a4f117c548028101c5b6855e10923ea9d1f635af53ad20c5868ff428c364d454a7b57fe391b89c704982275410c3c5099cca5aeee00d76e169a + languageName: node + linkType: hard + +"ltgt@npm:^2.1.2": + version: 2.2.1 + resolution: "ltgt@npm:2.2.1" + checksum: 7e3874296f7538bc8087b428ac4208008d7b76916354b34a08818ca7c83958c1df10ec427eeeaad895f6b81e41e24745b18d30f89abcc21d228b94f6961d50a2 + languageName: node + linkType: hard + +"lunr-languages@npm:^1.4.0": + version: 1.14.0 + resolution: "lunr-languages@npm:1.14.0" + checksum: 05dd6338af6897932f64f9cb735d5b48f9905d892499b22a3f3abc279b2ac71a6bce0fdfe59c01464c6ad3f8e44e2956ba0637f092535239793bbadf4540e72d + languageName: node + linkType: hard + +"lunr@npm:^2.3.9": + version: 2.3.9 + resolution: "lunr@npm:2.3.9" + checksum: 176719e24fcce7d3cf1baccce9dd5633cd8bdc1f41ebe6a180112e5ee99d80373fe2454f5d4624d437e5a8319698ca6837b9950566e15d2cae5f2a543a3db4b8 + languageName: node + linkType: hard + +"make-dir@npm:^3.0.0, make-dir@npm:^3.0.2, make-dir@npm:^3.1.0": + version: 3.1.0 + resolution: "make-dir@npm:3.1.0" + dependencies: + semver: ^6.0.0 + checksum: 484200020ab5a1fdf12f393fe5f385fc8e4378824c940fba1729dcd198ae4ff24867bc7a5646331e50cead8abff5d9270c456314386e629acec6dff4b8016b78 + languageName: node + linkType: hard + +"make-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "make-dir@npm:4.0.0" + dependencies: + semver: ^7.5.3 + checksum: bf0731a2dd3aab4db6f3de1585cea0b746bb73eb5a02e3d8d72757e376e64e6ada190b1eddcde5b2f24a81b688a9897efd5018737d05e02e2a671dda9cff8a8a + languageName: node + linkType: hard + +"make-error@npm:^1.1.1": + version: 1.3.6 + resolution: "make-error@npm:1.3.6" + checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" + dependencies: + "@npmcli/agent": ^2.0.0 + cacache: ^18.0.0 + http-cache-semantics: ^4.1.1 + is-lambda: ^1.0.1 + minipass: ^7.0.2 + minipass-fetch: ^3.0.0 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + negotiator: ^0.6.3 + promise-retry: ^2.0.1 + ssri: ^10.0.0 + checksum: 7c7a6d381ce919dd83af398b66459a10e2fe8f4504f340d1d090d3fa3d1b0c93750220e1d898114c64467223504bd258612ba83efbc16f31b075cd56de24b4af + languageName: node + linkType: hard + +"mark.js@npm:^8.11.1": + version: 8.11.1 + resolution: "mark.js@npm:8.11.1" + checksum: aa6b9ae1c67245348d5b7abd253ef2acd6bb05c6be358d7d192416d964e42665fc10e0e865591c6f93ab9b57e8da1f23c23216e8ebddb580905ea7a0c0df15d4 + languageName: node + linkType: hard + +"markdown-escapes@npm:^1.0.0": + version: 1.0.4 + resolution: "markdown-escapes@npm:1.0.4" + checksum: 6833a93d72d3f70a500658872312c6fa8015c20cc835a85ae6901fa232683fbc6ed7118ebe920fea7c80039a560f339c026597d96eee0e9de602a36921804997 + languageName: node + linkType: hard + +"markdown-extensions@npm:^2.0.0": + version: 2.0.0 + resolution: "markdown-extensions@npm:2.0.0" + checksum: ec4ffcb0768f112e778e7ac74cb8ef22a966c168c3e6c29829f007f015b0a0b5c79c73ee8599a0c72e440e7f5cfdbf19e80e2d77b9a313b8f66e180a330cf1b2 + languageName: node + linkType: hard + +"markdown-table@npm:^3.0.0": + version: 3.0.3 + resolution: "markdown-table@npm:3.0.3" + checksum: 8fcd3d9018311120fbb97115987f8b1665a603f3134c93fbecc5d1463380c8036f789e2a62c19432058829e594fff8db9ff81c88f83690b2f8ed6c074f8d9e10 + languageName: node + linkType: hard + +"marked@npm:^4.3.0": + version: 4.3.0 + resolution: "marked@npm:4.3.0" + bin: + marked: bin/marked.js + checksum: 0db6817893952c3ec710eb9ceafb8468bf5ae38cb0f92b7b083baa13d70b19774674be04db5b817681fa7c5c6a088f61300815e4dd75a59696f4716ad69f6260 + languageName: node + linkType: hard + +"marky@npm:^1.2.2": + version: 1.2.5 + resolution: "marky@npm:1.2.5" + checksum: 823b946677749551cdfc3b5221685478b5d1b9cc0dc03eff977c6f9a615fb05c67559f9556cb3c0fcb941a9ea0e195e37befd83026443396ccee8b724f54f4c5 + languageName: node + linkType: hard + +"md5.js@npm:^1.3.4": + version: 1.3.5 + resolution: "md5.js@npm:1.3.5" + dependencies: + hash-base: ^3.0.0 + inherits: ^2.0.1 + safe-buffer: ^5.1.2 + checksum: 098494d885684bcc4f92294b18ba61b7bd353c23147fbc4688c75b45cb8590f5a95fd4584d742415dcc52487f7a1ef6ea611cfa1543b0dc4492fe026357f3f0c + languageName: node + linkType: hard + +"mdast-squeeze-paragraphs@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-squeeze-paragraphs@npm:4.0.0" + dependencies: + unist-util-remove: ^2.0.0 + checksum: dfe8ec8e8a62171f020e82b088cc35cb9da787736dc133a3b45ce8811782a93e69bf06d147072e281079f09fac67be8a36153ffffd9bfbf89ed284e4c4f56f75 + languageName: node + linkType: hard + +"mdast-util-definitions@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-definitions@npm:4.0.0" + dependencies: + unist-util-visit: ^2.0.0 + checksum: 2325f20b82b3fb8cb5fda77038ee0bbdd44f82cfca7c48a854724b58bc1fe5919630a3ce7c45e210726df59d46c881d020b2da7a493bfd1ee36eb2bbfef5d78e + languageName: node + linkType: hard + +"mdast-util-directive@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-directive@npm:3.0.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + parse-entities: ^4.0.0 + stringify-entities: ^4.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 593afdc4f39f99bb198f3774bf4648cb546cb99a055e40c82262a7faab10926d2529a725d0d3945300ed0a1f07c6c84215a3f76b899a89b3f410ec7375bbab17 + languageName: node + linkType: hard + +"mdast-util-find-and-replace@npm:^3.0.0, mdast-util-find-and-replace@npm:^3.0.1": + version: 3.0.1 + resolution: "mdast-util-find-and-replace@npm:3.0.1" + dependencies: + "@types/mdast": ^4.0.0 + escape-string-regexp: ^5.0.0 + unist-util-is: ^6.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 05d5c4ff02e31db2f8a685a13bcb6c3f44e040bd9dfa54c19a232af8de5268334c8755d79cb456ed4cced1300c4fb83e88444c7ae8ee9ff16869a580f29d08cd + languageName: node + linkType: hard + +"mdast-util-from-markdown@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-from-markdown@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + mdast-util-to-string: ^4.0.0 + micromark: ^4.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-decode-string: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 4e8d8a46b4b588486c41b80c39da333a91593bc8d60cd7421c6cd3c22003b8e5a62478292fb7bc97b9255b6301a2250cca32340ef43c309156e215453c5b92be + languageName: node + linkType: hard + +"mdast-util-frontmatter@npm:^2.0.0": + version: 2.0.1 + resolution: "mdast-util-frontmatter@npm:2.0.1" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + escape-string-regexp: ^5.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + checksum: 86a7c8d9eb183be2621d6d9134b9d33df2a3647e3255f68a9796e2425e25643ffae00a501e36c57d9c10973087b94aa5a2ffd865d33cdd274cc9b88cd2d90a2e + languageName: node + linkType: hard + +"mdast-util-gfm-autolink-literal@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-autolink-literal@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + ccount: ^2.0.0 + devlop: ^1.0.0 + mdast-util-find-and-replace: ^3.0.0 + micromark-util-character: ^2.0.0 + checksum: 10322662e5302964bed7c9829c5fd3b0c9899d4f03e63fb8620ab141cf4f3de9e61fcb4b44d46aacc8a23f82bcd5d900980a211825dfe026b1dab5fdbc3e8742 + languageName: node + linkType: hard + +"mdast-util-gfm-footnote@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-footnote@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.1.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + checksum: 45d26b40e7a093712e023105791129d76e164e2168d5268e113298a22de30c018162683fb7893cdc04ab246dac0087eed708b2a136d1d18ed2b32b3e0cae4a79 + languageName: node + linkType: hard + +"mdast-util-gfm-strikethrough@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-strikethrough@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: fe9b1d0eba9b791ff9001c008744eafe3dd7a81b085f2bf521595ce4a8e8b1b44764ad9361761ad4533af3e5d913d8ad053abec38172031d9ee32a8ebd1c7dbd + languageName: node + linkType: hard + +"mdast-util-gfm-table@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-table@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + markdown-table: ^3.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 063a627fd0993548fd63ca0c24c437baf91ba7d51d0a38820bd459bc20bf3d13d7365ef8d28dca99176dd5eb26058f7dde51190479c186dfe6af2e11202957c9 + languageName: node + linkType: hard + +"mdast-util-gfm-task-list-item@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-task-list-item@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 37db90c59b15330fc54d790404abf5ef9f2f83e8961c53666fe7de4aab8dd5e6b3c296b6be19797456711a89a27840291d8871ff0438e9b4e15c89d170efe072 + languageName: node + linkType: hard + +"mdast-util-gfm@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-gfm@npm:3.0.0" + dependencies: + mdast-util-from-markdown: ^2.0.0 + mdast-util-gfm-autolink-literal: ^2.0.0 + mdast-util-gfm-footnote: ^2.0.0 + mdast-util-gfm-strikethrough: ^2.0.0 + mdast-util-gfm-table: ^2.0.0 + mdast-util-gfm-task-list-item: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 62039d2f682ae3821ea1c999454863d31faf94d67eb9b746589c7e136076d7fb35fabc67e02f025c7c26fd7919331a0ee1aabfae24f565d9a6a9ebab3371c626 + languageName: node + linkType: hard + +"mdast-util-math@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-math@npm:3.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + longest-streak: ^3.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.1.0 + unist-util-remove-position: ^5.0.0 + checksum: dc7dfb14aec2ec143420f2d92f80c5e6d69293d7cfb6b8180e7f411ce4e1314b5cf4a8d3345eefe06ab0ddd95e3c7801c4174b343fd2c26741180ca4dbad5371 + languageName: node + linkType: hard + +"mdast-util-mdx-expression@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-mdx-expression@npm:2.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 4e1183000e183e07a7264e192889b4fd57372806103031c71b9318967f85fd50a5dd0f92ef14f42c331e77410808f5de3341d7bc8ad4ee91b7fa8f0a30043a8a + languageName: node + linkType: hard + +"mdast-util-mdx-jsx@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-mdx-jsx@npm:3.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + ccount: ^2.0.0 + devlop: ^1.1.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + parse-entities: ^4.0.0 + stringify-entities: ^4.0.0 + unist-util-remove-position: ^5.0.0 + unist-util-stringify-position: ^4.0.0 + vfile-message: ^4.0.0 + checksum: 48fe1ba617205f3776ca2030d195adbdb42bb6c53326534db3f5bdd28abe7895103af8c4dfda7cbe2911e8cd71921bc8a82fe40856565e57af8b4f8a79c8c126 + languageName: node + linkType: hard + +"mdast-util-mdx@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-mdx@npm:3.0.0" + dependencies: + mdast-util-from-markdown: ^2.0.0 + mdast-util-mdx-expression: ^2.0.0 + mdast-util-mdx-jsx: ^3.0.0 + mdast-util-mdxjs-esm: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: e2b007d826fcd49fd57ed03e190753c8b0f7d9eff6c7cb26ba609cde15cd3a472c0cd5e4a1ee3e39a40f14be22fdb57de243e093cea0c064d6f3366cff3e3af2 + languageName: node + linkType: hard + +"mdast-util-mdxjs-esm@npm:^2.0.0": + version: 2.0.1 + resolution: "mdast-util-mdxjs-esm@npm:2.0.1" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 1f9dad04d31d59005332e9157ea9510dc1d03092aadbc607a10475c7eec1c158b475aa0601a3a4f74e13097ca735deb8c2d9d37928ddef25d3029fd7c9e14dc3 + languageName: node + linkType: hard + +"mdast-util-phrasing@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-phrasing@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + unist-util-is: ^6.0.0 + checksum: 95d5d8e18d5ea6dbfe2ee4ed1045961372efae9077e5c98e10bfef7025ee3fd9449f9a82840068ff50aa98fa43af0a0a14898ae10b5e46e96edde01e2797df34 + languageName: node + linkType: hard + +"mdast-util-to-hast@npm:10.0.1": + version: 10.0.1 + resolution: "mdast-util-to-hast@npm:10.0.1" + dependencies: + "@types/mdast": ^3.0.0 + "@types/unist": ^2.0.0 + mdast-util-definitions: ^4.0.0 + mdurl: ^1.0.0 + unist-builder: ^2.0.0 + unist-util-generated: ^1.0.0 + unist-util-position: ^3.0.0 + unist-util-visit: ^2.0.0 + checksum: e5f385757df7e9b37db4d6f326bf7b4fc1b40f9ad01fc335686578f44abe0ba46d3e60af4d5e5b763556d02e65069ef9a09c49db049b52659203a43e7fa9084d + languageName: node + linkType: hard + +"mdast-util-to-hast@npm:^13.0.0": + version: 13.0.2 + resolution: "mdast-util-to-hast@npm:13.0.2" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + "@ungap/structured-clone": ^1.0.0 + devlop: ^1.0.0 + micromark-util-sanitize-uri: ^2.0.0 + trim-lines: ^3.0.0 + unist-util-position: ^5.0.0 + unist-util-visit: ^5.0.0 + checksum: 8fef6c3752476461d9c00b1dea4f141bc7d980e1b3bac7bd965bc68f532b6d30fb1c9e810433327c167176e68e071b8f4ab5a45355954857dc095c878421f35e + languageName: node + linkType: hard + +"mdast-util-to-markdown@npm:^2.0.0, mdast-util-to-markdown@npm:^2.1.0": + version: 2.1.0 + resolution: "mdast-util-to-markdown@npm:2.1.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + longest-streak: ^3.0.0 + mdast-util-phrasing: ^4.0.0 + mdast-util-to-string: ^4.0.0 + micromark-util-decode-string: ^2.0.0 + unist-util-visit: ^5.0.0 + zwitch: ^2.0.0 + checksum: 3a2cf3957e23b34e2e092e6e76ae72ee0b8745955bd811baba6814cf3a3d916c3fd52264b4b58f3bb3d512a428f84a1e998b6fc7e28434e388a9ae8fb6a9c173 + languageName: node + linkType: hard + +"mdast-util-to-string@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-to-string@npm:2.0.0" + checksum: 0b2113ada10e002fbccb014170506dabe2f2ddacaacbe4bc1045c33f986652c5a162732a2c057c5335cdb58419e2ad23e368e5be226855d4d4e280b81c4e9ec2 + languageName: node + linkType: hard + +"mdast-util-to-string@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-to-string@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + checksum: 35489fb5710d58cbc2d6c8b6547df161a3f81e0f28f320dfb3548a9393555daf07c310c0c497708e67ed4dfea4a06e5655799e7d631ca91420c288b4525d6c29 + languageName: node + linkType: hard + +"mdn-data@npm:2.0.14": + version: 2.0.14 + resolution: "mdn-data@npm:2.0.14" + checksum: 9d0128ed425a89f4cba8f787dca27ad9408b5cb1b220af2d938e2a0629d17d879a34d2cb19318bdb26c3f14c77dd5dfbae67211f5caaf07b61b1f2c5c8c7dc16 + languageName: node + linkType: hard + +"mdn-data@npm:2.0.28": + version: 2.0.28 + resolution: "mdn-data@npm:2.0.28" + checksum: f51d587a6ebe8e426c3376c74ea6df3e19ec8241ed8e2466c9c8a3904d5d04397199ea4f15b8d34d14524b5de926d8724ae85207984be47e165817c26e49e0aa + languageName: node + linkType: hard + +"mdn-data@npm:2.0.30": + version: 2.0.30 + resolution: "mdn-data@npm:2.0.30" + checksum: d6ac5ac7439a1607df44b22738ecf83f48e66a0874e4482d6424a61c52da5cde5750f1d1229b6f5fa1b80a492be89465390da685b11f97d62b8adcc6e88189aa + languageName: node + linkType: hard + +"mdurl@npm:^1.0.0": + version: 1.0.1 + resolution: "mdurl@npm:1.0.1" + checksum: 71731ecba943926bfbf9f9b51e28b5945f9411c4eda80894221b47cc105afa43ba2da820732b436f0798fd3edbbffcd1fc1415843c41a87fea08a41cc1e3d02b + languageName: node + linkType: hard + +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 + languageName: node + linkType: hard + +"memfs@npm:^3.1.2, memfs@npm:^3.4.3": + version: 3.5.3 + resolution: "memfs@npm:3.5.3" + dependencies: + fs-monkey: ^1.0.4 + checksum: 18dfdeacad7c8047b976a6ccd58bc98ba76e122ad3ca0e50a21837fe2075fc0d9aafc58ab9cf2576c2b6889da1dd2503083f2364191b695273f40969db2ecc44 + languageName: node + linkType: hard + +"memfs@npm:^4.6.0": + version: 4.6.0 + resolution: "memfs@npm:4.6.0" + dependencies: + json-joy: ^9.2.0 + thingies: ^1.11.1 + peerDependencies: + tslib: 2 + checksum: b32a35bee9f96dc011605f3bb39e74e6d2a5de51c952a77bb38a0dfabd3381c40ae382d27f385aa290edee8081597fb1a3b41a07bb3f775fd55312dc30ac1d9d + languageName: node + linkType: hard + +"memorystream@npm:^0.3.1": + version: 0.3.1 + resolution: "memorystream@npm:0.3.1" + checksum: f18b42440d24d09516d01466c06adf797df7873f0d40aa7db02e5fb9ed83074e5e65412d0720901d7069363465f82dc4f8bcb44f0cde271567a61426ce6ca2e9 + languageName: node + linkType: hard + +"merge-descriptors@npm:1.0.1": + version: 1.0.1 + resolution: "merge-descriptors@npm:1.0.1" + checksum: 5abc259d2ae25bb06d19ce2b94a21632583c74e2a9109ee1ba7fd147aa7362b380d971e0251069f8b3eb7d48c21ac839e21fa177b335e82c76ec172e30c31a26 + languageName: node + linkType: hard + +"merge-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-stream@npm:2.0.0" + checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 + languageName: node + linkType: hard + +"merge2@npm:^1.3.0, merge2@npm:^1.4.1": + version: 1.4.1 + resolution: "merge2@npm:1.4.1" + checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 + languageName: node + linkType: hard + +"methods@npm:~1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: 0917ff4041fa8e2f2fda5425a955fe16ca411591fbd123c0d722fcf02b73971ed6f764d85f0a6f547ce49ee0221ce2c19a5fa692157931cecb422984f1dcd13a + languageName: node + linkType: hard + +"micromark-core-commonmark@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-core-commonmark@npm:2.0.0" + dependencies: + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-factory-destination: ^2.0.0 + micromark-factory-label: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-factory-title: ^2.0.0 + micromark-factory-whitespace: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-classify-character: ^2.0.0 + micromark-util-html-tag-name: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9c12fb580cf4ce71f60872043bd2794efe129f44d7b2b73afa155bbc0a66b7bc35655ba8cef438a6bd068441837ed3b6dc6ad7e5a18f815462c1750793e03a42 + languageName: node + linkType: hard + +"micromark-extension-directive@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-directive@npm:3.0.0" + dependencies: + devlop: ^1.0.0 + micromark-factory-space: ^2.0.0 + micromark-factory-whitespace: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + parse-entities: ^4.0.0 + checksum: 8350106bdf039a544cba64cf7932261a710e07d73d43d6c645dd2b16577f30ebd04abf762e8ca74266f5de19938e1eeff6c237d79f8244dea23aef7f90df2c31 + languageName: node + linkType: hard + +"micromark-extension-frontmatter@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-frontmatter@npm:2.0.0" + dependencies: + fault: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: f68032df38c00ae47de15b63bcd72515bfcce39de4a9262a3a1ac9c5990f253f8e41bdc65fd17ec4bb3d144c32529ce0829571331e4901a9a413f1a53785d1e8 + languageName: node + linkType: hard + +"micromark-extension-gfm-autolink-literal@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-autolink-literal@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: fa16d59528239262d6d04d539a052baf1f81275954ec8bfadea40d81bfc25667d5c8e68b225a5358626df5e30a3933173a67fdad2fed011d37810a10b770b0b2 + languageName: node + linkType: hard + +"micromark-extension-gfm-footnote@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-footnote@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: a426fddecfac6144fc622b845cd2dc09d46faa75be5b76ff022cb76a03301b1d4929a5e5e41e071491787936be65e03d0b03c7aebc0e0136b3cdbfadadd6632c + languageName: node + linkType: hard + +"micromark-extension-gfm-strikethrough@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-strikethrough@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-classify-character: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 4e35fbbf364bfce08066b70acd94b9d393a8fd09a5afbe0bae70d0c8a174640b1ba86ab6b78ee38f411a813e2a718b07959216cf0063d823ba1c569a7694e5ad + languageName: node + linkType: hard + +"micromark-extension-gfm-table@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-table@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 71484dcf8db7b189da0528f472cc81e4d6d1a64ae43bbe7fcb7e2e1dba758a0a4f785f9f1afb9459fe5b4a02bbe023d78c95c05204414a14083052eb8219e5eb + languageName: node + linkType: hard + +"micromark-extension-gfm-tagfilter@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-tagfilter@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: cf21552f4a63592bfd6c96ae5d64a5f22bda4e77814e3f0501bfe80e7a49378ad140f827007f36044666f176b3a0d5fea7c2e8e7973ce4b4579b77789f01ae95 + languageName: node + linkType: hard + +"micromark-extension-gfm-task-list-item@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-extension-gfm-task-list-item@npm:2.0.1" + dependencies: + devlop: ^1.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 80e569ab1a1d1f89d86af91482e9629e24b7e3f019c9d7989190f36a9367c6de723b2af48e908c1b73479f35b2215d3d38c1fdbf02ab01eb2fc90a59d1cf4465 + languageName: node + linkType: hard + +"micromark-extension-gfm@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-gfm@npm:3.0.0" + dependencies: + micromark-extension-gfm-autolink-literal: ^2.0.0 + micromark-extension-gfm-footnote: ^2.0.0 + micromark-extension-gfm-strikethrough: ^2.0.0 + micromark-extension-gfm-table: ^2.0.0 + micromark-extension-gfm-tagfilter: ^2.0.0 + micromark-extension-gfm-task-list-item: ^2.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 2060fa62666a09532d6b3a272d413bc1b25bbb262f921d7402795ac021e1362c8913727e33d7528d5b4ccaf26922ec51208c43f795a702964817bc986de886c9 + languageName: node + linkType: hard + +"micromark-extension-math@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-math@npm:3.0.0" + dependencies: + "@types/katex": ^0.16.0 + devlop: ^1.0.0 + katex: ^0.16.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 14d313ea58f711d69c567951870f8d8517384cd90318d8b608b4eabb2fea2278c7de1ca38fa86067704cba679b5a82be243680436c1bc26c4c4978b28fdf647c + languageName: node + linkType: hard + +"micromark-extension-mdx-expression@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdx-expression@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + micromark-factory-mdx-expression: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-events-to-acorn: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: abd6ba0acdebc03bc0836c51a1ec4ca28e0be86f10420dd8cfbcd6c10dd37cd3f31e7c8b9792e9276e7526748883f4a30d0803d72b6285dae47d4e5348c23a10 + languageName: node + linkType: hard + +"micromark-extension-mdx-jsx@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdx-jsx@npm:3.0.0" + dependencies: + "@types/acorn": ^4.0.0 + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + estree-util-is-identifier-name: ^3.0.0 + micromark-factory-mdx-expression: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + vfile-message: ^4.0.0 + checksum: 5e2f45d381d1ce43afadc5376427b42ef8cd2a574ca3658473254eabe84db99ef1abc03055b3d86728fac7f1edfb1076e6f2f322ed8bfb1f2f14cafc2c8f0d0e + languageName: node + linkType: hard + +"micromark-extension-mdx-md@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-mdx-md@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: 7daf03372fd7faddf3f0ac87bdb0debb0bb770f33b586f72251e1072b222ceee75400ab6194c0e130dbf1e077369a5b627be6e9130d7a2e9e6b849f0d18ff246 + languageName: node + linkType: hard + +"micromark-extension-mdxjs-esm@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdxjs-esm@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-events-to-acorn: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-position-from-estree: ^2.0.0 + vfile-message: ^4.0.0 + checksum: fb33d850200afce567b95c90f2f7d42259bd33eea16154349e4fa77c3ec934f46c8e5c111acea16321dce3d9f85aaa4c49afe8b810e31b34effc11617aeee8f6 + languageName: node + linkType: hard + +"micromark-extension-mdxjs@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdxjs@npm:3.0.0" + dependencies: + acorn: ^8.0.0 + acorn-jsx: ^5.0.0 + micromark-extension-mdx-expression: ^3.0.0 + micromark-extension-mdx-jsx: ^3.0.0 + micromark-extension-mdx-md: ^2.0.0 + micromark-extension-mdxjs-esm: ^3.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 7da6f0fb0e1e0270a2f5ad257e7422cc16e68efa7b8214c63c9d55bc264cb872e9ca4ac9a71b9dfd13daf52e010f730bac316086f4340e4fcc6569ec699915bf + languageName: node + linkType: hard + +"micromark-factory-destination@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-destination@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: d36e65ed1c072ff4148b016783148ba7c68a078991154625723e24bda3945160268fb91079fb28618e1613c2b6e70390a8ddc544c45410288aa27b413593071a + languageName: node + linkType: hard + +"micromark-factory-label@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-label@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: c021dbd0ed367610d35f2bae21209bc804d1a6d1286ffce458fd6a717f4d7fe581a7cba7d5c2d7a63757c44eb927c80d6a571d6ea7969fae1b48ab6461d109c4 + languageName: node + linkType: hard + +"micromark-factory-mdx-expression@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-factory-mdx-expression@npm:2.0.1" + dependencies: + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-events-to-acorn: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-position-from-estree: ^2.0.0 + vfile-message: ^4.0.0 + checksum: 2ba0ae939d0174a5e5331b1a4c203b96862ccf06e8903d6bdcc2d51f75515e52d407cd394afcd182f9ff0e877dc2a14e3fa430ced0131e156650d45104de8311 + languageName: node + linkType: hard + +"micromark-factory-space@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-factory-space@npm:1.1.0" + dependencies: + micromark-util-character: ^1.0.0 + micromark-util-types: ^1.0.0 + checksum: b58435076b998a7e244259a4694eb83c78915581206b6e7fc07b34c6abd36a1726ade63df8972fbf6c8fa38eecb9074f4e17be8d53f942e3b3d23d1a0ecaa941 + languageName: node + linkType: hard + +"micromark-factory-space@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-space@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 4ffdcdc2f759887bbb356500cb460b3915ecddcb5d85c3618d7df68ad05d13ed02b1153ee1845677b7d8126df8f388288b84fcf0d943bd9c92bcc71cd7222e37 + languageName: node + linkType: hard + +"micromark-factory-title@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-title@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 39e1ac23af3554e6e652e56065579bc7faf21ade7b8704b29c175871b4152b7109b790bb3cae0f7e088381139c6bac9553b8400772c3d322e4fa635f813a3578 + languageName: node + linkType: hard + +"micromark-factory-whitespace@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-whitespace@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9587c2546d1a58b4d5472b42adf05463f6212d0449455285662d63cd8eaed89c6b159ac82713fcee5f9dd88628c24307d9533cccd8971a2f3f4d48702f8f850a + languageName: node + linkType: hard + +"micromark-util-character@npm:^1.0.0, micromark-util-character@npm:^1.1.0": + version: 1.2.0 + resolution: "micromark-util-character@npm:1.2.0" + dependencies: + micromark-util-symbol: ^1.0.0 + micromark-util-types: ^1.0.0 + checksum: 089e79162a19b4a28731736246579ab7e9482ac93cd681c2bfca9983dcff659212ef158a66a5957e9d4b1dba957d1b87b565d85418a5b009f0294f1f07f2aaac + languageName: node + linkType: hard + +"micromark-util-character@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-character@npm:2.0.1" + dependencies: + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 318d6e16fdcbe9d89e18b8e7796568d986abbb10a9f3037b7ac9b92a236bcc962f3cd380e26a7c49df40fd1d9ca33eb546268956345b662f4c4ca4962c7695f2 + languageName: node + linkType: hard + +"micromark-util-chunked@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-chunked@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: 324f95cccdae061332a8241936eaba6ef0782a1e355bac5c607ad2564fd3744929be7dc81651315a2921535747a33243e6a5606bcb64b7a56d49b6d74ea1a3d4 + languageName: node + linkType: hard + +"micromark-util-classify-character@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-classify-character@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 086e52904deffebb793fb1c08c94aabb8901f76958142dfc3a6282890ebaa983b285e69bd602b9d507f1b758ed38e75a994d2ad9fbbefa7de2584f67a16af405 + languageName: node + linkType: hard + +"micromark-util-combine-extensions@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-combine-extensions@npm:2.0.0" + dependencies: + micromark-util-chunked: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 107c47700343f365b4ed81551e18bc3458b573c500e56ac052b2490bd548adc475216e41d2271633a8867fac66fc22ba3e0a2d74a31ed79b9870ca947eb4e3ba + languageName: node + linkType: hard + +"micromark-util-decode-numeric-character-reference@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-decode-numeric-character-reference@npm:2.0.1" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: 9512507722efd2033a9f08715eeef787fbfe27e23edf55db21423d46d82ab46f76c89b4f960be3f5e50a2d388d89658afc0647989cf256d051e9ea01277a1adb + languageName: node + linkType: hard + +"micromark-util-decode-string@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-decode-string@npm:2.0.0" + dependencies: + decode-named-character-reference: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: a75daf32a4a6b549e9f19b4d833ebfeb09a32a9a1f9ce50f35dec6b6a3e4f9f121f49024ba7f9c91c55ebe792f7c7a332fc9604795181b6a612637df0df5b959 + languageName: node + linkType: hard + +"micromark-util-encode@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-encode@npm:2.0.0" + checksum: 853a3f33fce72aaf4ffa60b7f2b6fcfca40b270b3466e1b96561b02185d2bd8c01dd7948bc31a24ac014f4cc854e545ca9a8e9cf7ea46262f9d24c9e88551c66 + languageName: node + linkType: hard + +"micromark-util-events-to-acorn@npm:^2.0.0": + version: 2.0.2 + resolution: "micromark-util-events-to-acorn@npm:2.0.2" + dependencies: + "@types/acorn": ^4.0.0 + "@types/estree": ^1.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + estree-util-visit: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + vfile-message: ^4.0.0 + checksum: bcb3eeac52a4ae5c3ca3d8cff514de3a7d1f272d9a94cce26a08c578bef64df4d61820874c01207e92fcace9eae5c9a7ecdddef0c6e10014b255a07b7880bf94 + languageName: node + linkType: hard + +"micromark-util-html-tag-name@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-html-tag-name@npm:2.0.0" + checksum: d786d4486f93eb0ac5b628779809ca97c5dc60f3c9fc03eb565809831db181cf8cb7f05f9ac76852f3eb35461af0f89fa407b46f3a03f4f97a96754d8dc540d8 + languageName: node + linkType: hard + +"micromark-util-normalize-identifier@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-normalize-identifier@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: b36da2d3fd102053dadd953ce5c558328df12a63a8ac0e5aad13d4dda8e43b6a5d4a661baafe0a1cd8a260bead4b4a8e6e0e74193dd651e8484225bd4f4e68aa + languageName: node + linkType: hard + +"micromark-util-resolve-all@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-resolve-all@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: 31fe703b85572cb3f598ebe32750e59516925c7ff1f66cfe6afaebe0771a395a9eaa770787f2523d3c46082ea80e6c14f83643303740b3d650af7c96ebd30ccc + languageName: node + linkType: hard + +"micromark-util-sanitize-uri@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-sanitize-uri@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: ea4c28bbffcf2430e9aff2d18554296789a8b0a1f54ac24020d1dde76624a7f93e8f2a83e88cd5a846b6d2c4287b71b1142d1b89fa7f1b0363a9b33711a141fe + languageName: node + linkType: hard + +"micromark-util-subtokenize@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-subtokenize@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 77d9c7d59c05a20468d49ce2a3640e9cb268c083ccad02322f26c84e1094c25b44f4b8139ef0a247ca11a4fef7620c5bf82fbffd98acdb2989e79cbe7bd8f1db + languageName: node + linkType: hard + +"micromark-util-symbol@npm:^1.0.0, micromark-util-symbol@npm:^1.0.1": + version: 1.1.0 + resolution: "micromark-util-symbol@npm:1.1.0" + checksum: 02414a753b79f67ff3276b517eeac87913aea6c028f3e668a19ea0fc09d98aea9f93d6222a76ca783d20299af9e4b8e7c797fe516b766185dcc6e93290f11f88 + languageName: node + linkType: hard + +"micromark-util-symbol@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-symbol@npm:2.0.0" + checksum: fa4a05bff575d9fbf0ad96a1013003e3bb6087ed6b34b609a141b6c0d2137b57df594aca409a95f4c5fda199f227b56a7d8b1f82cea0768df161d8a3a3660764 + languageName: node + linkType: hard + +"micromark-util-types@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-types@npm:1.1.0" + checksum: b0ef2b4b9589f15aec2666690477a6a185536927ceb7aa55a0f46475852e012d75a1ab945187e5c7841969a842892164b15d58ff8316b8e0d6cc920cabd5ede7 + languageName: node + linkType: hard + +"micromark-util-types@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-types@npm:2.0.0" + checksum: 819fef3ab5770c37893d2a60381fb2694396c8d22803b6e103c830c3a1bc1490363c2b0470bb2acaaddad776dfbc2fc1fcfde39cb63c4f54d95121611672e3d0 + languageName: node + linkType: hard + +"micromark@npm:^4.0.0": + version: 4.0.0 + resolution: "micromark@npm:4.0.0" + dependencies: + "@types/debug": ^4.0.0 + debug: ^4.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: b84ab5ab1a0b28c063c52e9c2c9d7d44b954507235c10c9492d66e0b38f7de24bf298f914a1fbdf109f2a57a88cf0412de217c84cfac5fd60e3e42a74dbac085 + languageName: node + linkType: hard + +"micromatch@npm:^4.0.0, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": + version: 4.0.5 + resolution: "micromatch@npm:4.0.5" + dependencies: + braces: ^3.0.2 + picomatch: ^2.3.1 + checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc + languageName: node + linkType: hard + +"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f + languageName: node + linkType: hard + +"mime-db@npm:~1.33.0": + version: 1.33.0 + resolution: "mime-db@npm:1.33.0" + checksum: 281a0772187c9b8f6096976cb193ac639c6007ac85acdbb8dc1617ed7b0f4777fa001d1b4f1b634532815e60717c84b2f280201d55677fb850c9d45015b50084 + languageName: node + linkType: hard + +"mime-types@npm:2.1.18": + version: 2.1.18 + resolution: "mime-types@npm:2.1.18" + dependencies: + mime-db: ~1.33.0 + checksum: 729265eff1e5a0e87cb7f869da742a610679585167d2f2ec997a7387fc6aedf8e5cad078e99b0164a927bdf3ace34fca27430d6487456ad090cba5594441ba43 + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.18, mime-types@npm:^2.1.27, mime-types@npm:^2.1.31, mime-types@npm:~2.1.17, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: 1.52.0 + checksum: 89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836 + languageName: node + linkType: hard + +"mime@npm:1.6.0": + version: 1.6.0 + resolution: "mime@npm:1.6.0" + bin: + mime: cli.js + checksum: fef25e39263e6d207580bdc629f8872a3f9772c923c7f8c7e793175cee22777bbe8bba95e5d509a40aaa292d8974514ce634ae35769faa45f22d17edda5e8557 + languageName: node + linkType: hard + +"mimic-fn@npm:^2.1.0": + version: 2.1.0 + resolution: "mimic-fn@npm:2.1.0" + checksum: d2421a3444848ce7f84bd49115ddacff29c15745db73f54041edc906c14b131a38d05298dae3081667627a59b2eb1ca4b436ff2e1b80f69679522410418b478a + 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" + checksum: 034c78753b0e622bc03c983663b1cdf66d03861050e0c8606563d149bc2b02d63f62ce4d32be4ab50d0553ae0ffe647fc34d1f5281184c6e1e8cf4d85e8d9823 + languageName: node + linkType: hard + +"mimic-response@npm:^3.1.0": + version: 3.1.0 + resolution: "mimic-response@npm:3.1.0" + checksum: 25739fee32c17f433626bf19f016df9036b75b3d84a3046c7d156e72ec963dd29d7fc8a302f55a3d6c5a4ff24259676b15d915aad6480815a969ff2ec0836867 + languageName: node + linkType: hard + +"mimic-response@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-response@npm:4.0.0" + checksum: 33b804cc961efe206efdb1fca6a22540decdcfce6c14eb5c0c50e5ae9022267ab22ce8f5568b1f7247ba67500fe20d523d81e0e9f009b321ccd9d472e78d1850 + languageName: node + linkType: hard + +"mini-css-extract-plugin@npm:^2.6.1, mini-css-extract-plugin@npm:^2.7.6": + version: 2.7.6 + resolution: "mini-css-extract-plugin@npm:2.7.6" + dependencies: + schema-utils: ^4.0.0 + peerDependencies: + webpack: ^5.0.0 + checksum: be6f7cefc6275168eb0a6b8fe977083a18c743c9612c9f00e6c1a62c3393ca7960e93fba1a7ebb09b75f36a0204ad087d772c1ef574bc29c90c0e8175a3c0b83 + languageName: node + linkType: hard + +"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-assert@npm:1.0.1" + checksum: cc7974a9268fbf130fb055aff76700d7e2d8be5f761fb5c60318d0ed010d839ab3661a533ad29a5d37653133385204c503bfac995aaa4236f4e847461ea32ba7 + languageName: node + linkType: hard + +"minimalistic-crypto-utils@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-crypto-utils@npm:1.0.1" + checksum: 6e8a0422b30039406efd4c440829ea8f988845db02a3299f372fceba56ffa94994a9c0f2fd70c17f9969eedfbd72f34b5070ead9656a34d3f71c0bd72583a0ed + languageName: node + linkType: hard + +"minimatch@npm:3.1.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: ^1.1.7 + checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a + languageName: node + linkType: hard + +"minimatch@npm:5.0.1": + version: 5.0.1 + resolution: "minimatch@npm:5.0.1" + dependencies: + brace-expansion: ^2.0.1 + checksum: b34b98463da4754bc526b244d680c69d4d6089451ebe512edaf6dd9eeed0279399cfa3edb19233513b8f830bf4bfcad911dddcdf125e75074100d52f724774f0 + languageName: node + linkType: hard + +"minimatch@npm:^9.0.1, minimatch@npm:^9.0.3": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: ^2.0.1 + checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 + languageName: node + linkType: hard + +"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: ^7.0.3 + checksum: b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 + languageName: node + linkType: hard + +"minipass-fetch@npm:^3.0.0": + version: 3.0.4 + resolution: "minipass-fetch@npm:3.0.4" + dependencies: + encoding: ^0.1.13 + minipass: ^7.0.3 + minipass-sized: ^1.0.3 + minizlib: ^2.1.2 + dependenciesMeta: + encoding: + optional: true + checksum: af7aad15d5c128ab1ebe52e043bdf7d62c3c6f0cecb9285b40d7b395e1375b45dcdfd40e63e93d26a0e8249c9efd5c325c65575aceee192883970ff8cb11364a + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: ^3.0.0 + checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: ^3.0.0 + checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: ^3.0.0 + checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: ^4.0.0 + checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": + version: 7.0.4 + resolution: "minipass@npm:7.0.4" + checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: ^3.0.0 + yallist: ^4.0.0 + checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 + languageName: node + linkType: hard + +"mitt@npm:3.0.1": + version: 3.0.1 + resolution: "mitt@npm:3.0.1" + checksum: b55a489ac9c2949ab166b7f060601d3b6d893a852515ae9eca4e11df01c013876df777ea109317622b5c1c60e8aae252558e33c8c94e14124db38f64a39614b1 + languageName: node + linkType: hard + +"mkdirp@npm:^0.5.6": + version: 0.5.6 + resolution: "mkdirp@npm:0.5.6" + dependencies: + minimist: ^1.2.6 + bin: + mkdirp: bin/cmd.js + checksum: 0c91b721bb12c3f9af4b77ebf73604baf350e64d80df91754dc509491ae93bf238581e59c7188360cec7cb62fc4100959245a42cfe01834efedc5e9d068376c2 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f + languageName: node + linkType: hard + +"mnemonist@npm:^0.38.0": + version: 0.38.5 + resolution: "mnemonist@npm:0.38.5" + dependencies: + obliterator: ^2.0.0 + checksum: 66080afc1616866beb164e230c432964d6eed467cf37ad00e9c10161b8267928124ca8f1d0ecfea86c85568acfa62d54faaf646a86968d1135189a0fdfdd6b78 + languageName: node + linkType: hard + +"mocha-each@npm:^2.0.1": + version: 2.0.1 + resolution: "mocha-each@npm:2.0.1" + dependencies: + sprintf-js: ^1.0.3 + checksum: 0de01ce517c2f7e7c3e19ef3f444809913f2f1602cb2571e6a3f8cb7ef3040f4f01b0f9f11a317e4ec1aeb9d39ceae4947c96668560cf638fe4d02ea549c2d4c + languageName: node + linkType: hard + +"mocha@npm:^10.0.0, mocha@npm:^10.2.0": + version: 10.2.0 + resolution: "mocha@npm:10.2.0" + dependencies: + ansi-colors: 4.1.1 + browser-stdout: 1.3.1 + chokidar: 3.5.3 + debug: 4.3.4 + diff: 5.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 7.2.0 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 5.0.1 + ms: 2.1.3 + nanoid: 3.3.3 + serialize-javascript: 6.0.0 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 6.2.1 + yargs: 16.2.0 + yargs-parser: 20.2.4 + yargs-unparser: 2.0.0 + bin: + _mocha: bin/_mocha + mocha: bin/mocha.js + checksum: 406c45eab122ffd6ea2003c2f108b2bc35ba036225eee78e0c784b6fa2c7f34e2b13f1dbacef55a4fdf523255d76e4f22d1b5aacda2394bd11666febec17c719 + languageName: node + linkType: hard + +"mrmime@npm:^1.0.0": + version: 1.0.1 + resolution: "mrmime@npm:1.0.1" + checksum: cc979da44bbbffebaa8eaf7a45117e851f2d4cb46a3ada6ceb78130466a04c15a0de9a9ce1c8b8ba6f6e1b8618866b1352992bf1757d241c0ddca558b9f28a77 + languageName: node + linkType: hard + +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 0e6a22b8b746d2e0b65a430519934fefd41b6db0682e3477c10f60c76e947c4c0ad06f63ffdf1d78d335f83edee8c0aa928aa66a36c7cd95b69b26f468d527f4 + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f + languageName: node + linkType: hard + +"ms@npm:2.1.3, ms@npm:^2.1.1": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d + languageName: node + linkType: hard + +"multicast-dns@npm:^7.2.5": + version: 7.2.5 + resolution: "multicast-dns@npm:7.2.5" + dependencies: + dns-packet: ^5.2.2 + thunky: ^1.0.2 + bin: + multicast-dns: cli.js + checksum: 00b8a57df152d4cd0297946320a94b7c3cdf75a46a2247f32f958a8927dea42958177f9b7fdae69fab2e4e033fb3416881af1f5e9055a3e1542888767139e2fb + languageName: node + linkType: hard + +"nanocolors@npm:^0.2.1": + version: 0.2.13 + resolution: "nanocolors@npm:0.2.13" + checksum: 01ac5aab77295c66cef83ea5f595e22f5f91518f19fae12f93ca2cba98703f971e32611fea2983f333eb7e60604043005690f61d9759e7c0a32314942fe6ddb8 + languageName: node + linkType: hard + +"nanoid@npm:3.3.3": + version: 3.3.3 + resolution: "nanoid@npm:3.3.3" + bin: + nanoid: bin/nanoid.cjs + checksum: ada019402a07464a694553c61d2dca8a4353645a7d92f2830f0d487fedff403678a0bee5323a46522752b2eab95a0bc3da98b6cccaa7c0c55cd9975130e6d6f0 + languageName: node + linkType: hard + +"nanoid@npm:^3.1.25, nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" + bin: + nanoid: bin/nanoid.cjs + checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 + languageName: node + linkType: hard + +"natural-compare@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare@npm:1.4.0" + checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d + languageName: node + linkType: hard + +"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 + languageName: node + linkType: hard + +"neo-async@npm:^2.6.2": + version: 2.6.2 + resolution: "neo-async@npm:2.6.2" + checksum: deac9f8d00eda7b2e5cd1b2549e26e10a0faa70adaa6fdadca701cc55f49ee9018e427f424bac0c790b7c7e2d3068db97f3093f1093975f2acb8f8818b936ed9 + languageName: node + linkType: hard + +"netmask@npm:^2.0.2": + version: 2.0.2 + resolution: "netmask@npm:2.0.2" + checksum: c65cb8d3f7ea5669edddb3217e4c96910a60d0d9a4b52d9847ff6b28b2d0277cd8464eee0ef85133cdee32605c57940cacdd04a9a019079b091b6bba4cb0ec22 + languageName: node + linkType: hard + +"nise@npm:^5.1.5": + version: 5.1.5 + resolution: "nise@npm:5.1.5" + dependencies: + "@sinonjs/commons": ^2.0.0 + "@sinonjs/fake-timers": ^10.0.2 + "@sinonjs/text-encoding": ^0.7.1 + just-extend: ^4.0.2 + path-to-regexp: ^1.7.0 + checksum: c763dc62c5796cafa5c9268e14a5b34db6e6fa2f1dbc57a891fe5d7ea632a87868e22b5bb34965006f984630793ea11368351e94971163228d9e20b2e88edce8 + languageName: node + linkType: hard + +"no-case@npm:^3.0.4": + version: 3.0.4 + resolution: "no-case@npm:3.0.4" + dependencies: + lower-case: ^2.0.2 + tslib: ^2.0.3 + checksum: 0b2ebc113dfcf737d48dde49cfebf3ad2d82a8c3188e7100c6f375e30eafbef9e9124aadc3becef237b042fd5eb0aad2fd78669c20972d045bbe7fea8ba0be5c + languageName: node + linkType: hard + +"node-addon-api@npm:^2.0.0": + version: 2.0.2 + resolution: "node-addon-api@npm:2.0.2" + dependencies: + node-gyp: latest + checksum: 31fb22d674648204f8dd94167eb5aac896c841b84a9210d614bf5d97c74ef059cc6326389cf0c54d2086e35312938401d4cc82e5fcd679202503eb8ac84814f8 + languageName: node + linkType: hard + +"node-emoji@npm:^1.10.0": + version: 1.11.0 + resolution: "node-emoji@npm:1.11.0" + dependencies: + lodash: ^4.17.21 + checksum: e8c856c04a1645062112a72e59a98b203505ed5111ff84a3a5f40611afa229b578c7d50f1e6a7f17aa62baeea4a640d2e2f61f63afc05423aa267af10977fb2b + languageName: node + linkType: hard + +"node-emoji@npm:^2.1.0": + version: 2.1.3 + resolution: "node-emoji@npm:2.1.3" + dependencies: + "@sindresorhus/is": ^4.6.0 + char-regex: ^1.0.2 + emojilib: ^2.4.0 + skin-tone: ^2.0.0 + checksum: 9ae5a1fb12fd5ce6885f251f345986115de4bb82e7d06fdc943845fb19260d89d0aaaccbaf85cae39fe7aaa1fc391640558865ba690c9bb8a7236c3ac10bbab0 + languageName: node + linkType: hard + +"node-fetch@npm:^2.6.12": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: d76d2f5edb451a3f05b15115ec89fc6be39de37c6089f1b6368df03b91e1633fd379a7e01b7ab05089a25034b2023d959b47e59759cb38d88341b2459e89d6e5 + languageName: node + linkType: hard + +"node-forge@npm:^1": + version: 1.3.1 + resolution: "node-forge@npm:1.3.1" + checksum: 08fb072d3d670599c89a1704b3e9c649ff1b998256737f0e06fbd1a5bf41cae4457ccaee32d95052d80bbafd9ffe01284e078c8071f0267dc9744e51c5ed42a9 + languageName: node + linkType: hard + +"node-gyp-build@npm:^4.2.0": + version: 4.7.1 + resolution: "node-gyp-build@npm:4.7.1" + bin: + node-gyp-build: bin.js + node-gyp-build-optional: optional.js + node-gyp-build-test: build-test.js + checksum: 2ef8248021489db03be3e8098977cdc797b80a9b12b77c6dcb89b0dc89b8c62e6a482672ee298f61021740ae7f080fb33154cfec8fb158cec620f57b0fae87c0 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.0.1 + resolution: "node-gyp@npm:10.0.1" + dependencies: + env-paths: ^2.2.0 + exponential-backoff: ^3.1.1 + glob: ^10.3.10 + graceful-fs: ^4.2.6 + make-fetch-happen: ^13.0.0 + nopt: ^7.0.0 + proc-log: ^3.0.0 + semver: ^7.3.5 + tar: ^6.1.2 + which: ^4.0.0 + bin: + node-gyp: bin/node-gyp.js + checksum: 60a74e66d364903ce02049966303a57f898521d139860ac82744a5fdd9f7b7b3b61f75f284f3bfe6e6add3b8f1871ce305a1d41f775c7482de837b50c792223f + languageName: node + linkType: hard + +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 59443a2f77acac854c42d321bf1b43dea0aef55cd544c6a686e9816a697300458d4e82239e2d794ea05f7bbbc8a94500332e2d3ac3f11f52e4b16cbe638b3c41 + languageName: node + linkType: hard + +"node-releases@npm:^2.0.18": + version: 2.0.18 + resolution: "node-releases@npm:2.0.18" + checksum: ef55a3d853e1269a6d6279b7692cd6ff3e40bc74947945101138745bfdc9a5edabfe72cb19a31a8e45752e1910c4c65c77d931866af6357f242b172b7283f5b3 + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.0 + resolution: "nopt@npm:7.2.0" + dependencies: + abbrev: ^2.0.0 + bin: + nopt: bin/nopt.js + checksum: a9c0f57fb8cb9cc82ae47192ca2b7ef00e199b9480eed202482c962d61b59a7fbe7541920b2a5839a97b42ee39e288c0aed770e38057a608d7f579389dfde410 + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20 + languageName: node + linkType: hard + +"normalize-range@npm:^0.1.2": + version: 0.1.2 + resolution: "normalize-range@npm:0.1.2" + checksum: 9b2f14f093593f367a7a0834267c24f3cb3e887a2d9809c77d8a7e5fd08738bcd15af46f0ab01cc3a3d660386f015816b5c922cea8bf2ee79777f40874063184 + languageName: node + linkType: hard + +"normalize-url@npm:^4.1.0": + version: 4.5.1 + resolution: "normalize-url@npm:4.5.1" + checksum: 9a9dee01df02ad23e171171893e56e22d752f7cff86fb96aafeae074819b572ea655b60f8302e2d85dbb834dc885c972cc1c573892fea24df46b2765065dd05a + languageName: node + linkType: hard + +"normalize-url@npm:^6.0.1": + version: 6.1.0 + resolution: "normalize-url@npm:6.1.0" + checksum: 4a4944631173e7d521d6b80e4c85ccaeceb2870f315584fa30121f505a6dfd86439c5e3fdd8cd9e0e291290c41d0c3599f0cb12ab356722ed242584c30348e50 + languageName: node + linkType: hard + +"normalize-url@npm:^8.0.0": + version: 8.0.0 + resolution: "normalize-url@npm:8.0.0" + checksum: 24c20b75ebfd526d8453084692720b49d111c63c0911f1b7447427829597841eef5a8ba3f6bb93d6654007b991c1f5cd85da2c907800e439e2e2ec6c2abd0fc0 + languageName: node + linkType: hard + +"npm-run-path@npm:^4.0.1": + version: 4.0.1 + resolution: "npm-run-path@npm:4.0.1" + dependencies: + path-key: ^3.0.0 + checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 + languageName: node + linkType: hard + +"nprogress@npm:^0.2.0": + version: 0.2.0 + resolution: "nprogress@npm:0.2.0" + checksum: 66b7bec5d563ecf2d1c3d2815e6d5eb74ed815eee8563e0afa63d3f185ab1b9cf2ddd97e1ded263b9995c5019d26d600320e849e50f3747984daa033744619dc + languageName: node + linkType: hard + +"nth-check@npm:^2.0.1": + version: 2.1.1 + resolution: "nth-check@npm:2.1.1" + dependencies: + boolbase: ^1.0.0 + checksum: 5afc3dafcd1573b08877ca8e6148c52abd565f1d06b1eb08caf982e3fa289a82f2cae697ffb55b5021e146d60443f1590a5d6b944844e944714a5b549675bcd3 + languageName: node + linkType: hard + +"object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f + languageName: node + linkType: hard + +"object-inspect@npm:^1.9.0": + version: 1.13.1 + resolution: "object-inspect@npm:1.13.1" + checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f + languageName: node + linkType: hard + +"object-is@npm:^1.1.5": + version: 1.1.5 + resolution: "object-is@npm:1.1.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.3 + checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe + languageName: node + linkType: hard + +"object-keys@npm:^1.1.1": + version: 1.1.1 + resolution: "object-keys@npm:1.1.1" + checksum: b363c5e7644b1e1b04aa507e88dcb8e3a2f52b6ffd0ea801e4c7a62d5aa559affe21c55a07fd4b1fd55fc03a33c610d73426664b20032405d7b92a1414c34d6a + languageName: node + linkType: hard + +"object-keys@npm:~0.2.0": + version: 0.2.0 + resolution: "object-keys@npm:0.2.0" + dependencies: + foreach: ~2.0.1 + indexof: ~0.0.1 + is: ~0.2.6 + checksum: 4b96bab88fe9df22a03aec3c59a084bdffc789ad1318a39081e6b8389af6b9ab8571dd3776eed3ec5831137d057fb7ba76911552c6a6efd59b5d126ac3b6e432 + languageName: node + linkType: hard + +"object-keys@npm:~0.4.0": + version: 0.4.0 + resolution: "object-keys@npm:0.4.0" + checksum: 1be3ebe9b48c0d5eda8e4a30657d887a748cb42435e0e2eaf49faf557bdd602cd2b7558b8ce90a4eb2b8592d16b875a1900bce859cbb0f35b21c67e11a45313c + languageName: node + linkType: hard + +"object.assign@npm:^4.1.0, object.assign@npm:^4.1.4": + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" + dependencies: + call-bind: ^1.0.5 + define-properties: ^1.2.1 + has-symbols: ^1.0.3 + object-keys: ^1.1.1 + checksum: f9aeac0541661370a1fc86e6a8065eb1668d3e771f7dbb33ee54578201336c057b21ee61207a186dd42db0c62201d91aac703d20d12a79fc79c353eed44d4e25 + languageName: node + linkType: hard + +"obliterator@npm:^2.0.0": + version: 2.0.4 + resolution: "obliterator@npm:2.0.4" + checksum: f28ad35b6d812089315f375dc3e6e5f9bebf958ebe4b10ccd471c7115cbcf595e74bdac4783ae758e5b1f47e3096427fdb37cfa7bed566b132df92ff317b9a7c + languageName: node + linkType: hard + +"obuf@npm:^1.0.0, obuf@npm:^1.1.2": + version: 1.1.2 + resolution: "obuf@npm:1.1.2" + checksum: 41a2ba310e7b6f6c3b905af82c275bf8854896e2e4c5752966d64cbcd2f599cfffd5932006bcf3b8b419dfdacebb3a3912d5d94e10f1d0acab59876c8757f27f + languageName: node + linkType: hard + +"octal@npm:^1.0.0": + version: 1.0.0 + resolution: "octal@npm:1.0.0" + checksum: d648917f4f0a1042d7a4e230262aed00274c9791fe4795e9a2ce3b64ab7f2ca93e62cd55ca5ad4e4bd3fc375ca84d6919d7bf417be461790c1042503ac2c2310 + languageName: node + linkType: hard + +"on-finished@npm:2.4.1, on-finished@npm:^2.3.0": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: 1.1.1 + checksum: d20929a25e7f0bb62f937a425b5edeb4e4cde0540d77ba146ec9357f00b0d497cdb3b9b05b9c8e46222407d1548d08166bff69cc56dfa55ba0e4469228920ff0 + languageName: node + linkType: hard + +"on-headers@npm:~1.0.2": + version: 1.0.2 + resolution: "on-headers@npm:1.0.2" + checksum: 2bf13467215d1e540a62a75021e8b318a6cfc5d4fc53af8e8f84ad98dbcea02d506c6d24180cd62e1d769c44721ba542f3154effc1f7579a8288c9f7873ed8e5 + languageName: node + linkType: hard + +"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: 1 + checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 + languageName: node + linkType: hard + +"onetime@npm:^5.1.0, onetime@npm:^5.1.2": + version: 5.1.2 + resolution: "onetime@npm:5.1.2" + dependencies: + mimic-fn: ^2.1.0 + checksum: 2478859ef817fc5d4e9c2f9e5728512ddd1dbc9fb7829ad263765bb6d3b91ce699d6e2332eef6b7dff183c2f490bd3349f1666427eaba4469fba0ac38dfd0d34 + languageName: node + linkType: hard + +"only@npm:~0.0.2": + version: 0.0.2 + resolution: "only@npm:0.0.2" + checksum: d399710db867a1ef436dd3ce74499c87ece794aa81ab0370b5d153968766ee4aed2f98d3f92fc87c963e45b7a74d400d6f463ef651a5e7cfb861b15e88e9efe6 + languageName: node + linkType: hard + +"open@npm:^10.0.3": + version: 10.0.3 + resolution: "open@npm:10.0.3" + dependencies: + default-browser: ^5.2.1 + define-lazy-prop: ^3.0.0 + is-inside-container: ^1.0.0 + is-wsl: ^3.1.0 + checksum: 3c4b4eb3c08210f7b7b3f3311d36440f4b83f0641ac70e5e56d637f48d4a7736e0fd49a604eebe0a55c51223d77f9ced11912223cab12d5e9fdc866727c6cb1d + languageName: node + linkType: hard + +"open@npm:^8.0.2, open@npm:^8.0.9, open@npm:^8.4.0": + version: 8.4.2 + resolution: "open@npm:8.4.2" + dependencies: + define-lazy-prop: ^2.0.0 + is-docker: ^2.1.1 + is-wsl: ^2.2.0 + checksum: 6388bfff21b40cb9bd8f913f9130d107f2ed4724ea81a8fd29798ee322b361ca31fa2cdfb491a5c31e43a3996cfe9566741238c7a741ada8d7af1cb78d85cf26 + languageName: node + linkType: hard + +"opener@npm:^1.5.2": + version: 1.5.2 + resolution: "opener@npm:1.5.2" + bin: + opener: bin/opener-bin.js + checksum: 33b620c0d53d5b883f2abc6687dd1c5fd394d270dbe33a6356f2d71e0a2ec85b100d5bac94694198ccf5c30d592da863b2292c5539009c715a9c80c697b4f6cc + languageName: node + linkType: hard + +"optionator@npm:^0.9.3": + version: 0.9.3 + resolution: "optionator@npm:0.9.3" + dependencies: + "@aashutoshrathi/word-wrap": ^1.2.3 + deep-is: ^0.1.3 + fast-levenshtein: ^2.0.6 + levn: ^0.4.1 + prelude-ls: ^1.2.1 + type-check: ^0.4.0 + checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + languageName: node + linkType: hard + +"ordinal@npm:^1.0.3": + version: 1.0.3 + resolution: "ordinal@npm:1.0.3" + checksum: 6761c5b7606b6c4b0c22b4097dab4fe7ffcddacc49238eedf9c0ced877f5d4e4ad3f4fd43fefa1cc3f167cc54c7149267441b2ae85b81ccf13f45cf4b7947164 + languageName: node + linkType: hard + +"os-tmpdir@npm:~1.0.2": + version: 1.0.2 + resolution: "os-tmpdir@npm:1.0.2" + checksum: 5666560f7b9f10182548bf7013883265be33620b1c1b4a4d405c25be2636f970c5488ff3e6c48de75b55d02bde037249fe5dbfbb4c0fb7714953d56aed062e6d + languageName: node + linkType: hard + +"p-all@npm:^3.0.0": + version: 3.0.0 + resolution: "p-all@npm:3.0.0" + dependencies: + p-map: ^4.0.0 + checksum: 267a620c2330b14246b92008f4be8758debe74e1454c8fb5808544f51fd038ac4597dbeeaa1542f237794e613cd42e4f1a58c01e5a0a6a6b21340fef616257df + languageName: node + linkType: hard + +"p-cancelable@npm:^1.0.0": + version: 1.1.0 + resolution: "p-cancelable@npm:1.1.0" + checksum: 2db3814fef6d9025787f30afaee4496a8857a28be3c5706432cbad76c688a6db1874308f48e364a42f5317f5e41e8e7b4f2ff5c8ff2256dbb6264bc361704ece + languageName: node + linkType: hard + +"p-cancelable@npm:^3.0.0": + version: 3.0.0 + resolution: "p-cancelable@npm:3.0.0" + checksum: 2b5ae34218f9c2cf7a7c18e5d9a726ef9b165ef07e6c959f6738371509e747334b5f78f3bcdeb03d8a12dcb978faf641fd87eb21486ed7d36fb823b8ddef3219 + languageName: node + linkType: hard + +"p-limit@npm:^1.1.0": + version: 1.3.0 + resolution: "p-limit@npm:1.3.0" + dependencies: + p-try: ^1.0.0 + checksum: 281c1c0b8c82e1ac9f81acd72a2e35d402bf572e09721ce5520164e9de07d8274451378a3470707179ad13240535558f4b277f02405ad752e08c7d5b0d54fbfd + languageName: node + linkType: hard + +"p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": + version: 2.3.0 + resolution: "p-limit@npm:2.3.0" + dependencies: + p-try: ^2.0.0 + checksum: 84ff17f1a38126c3314e91ecfe56aecbf36430940e2873dadaa773ffe072dc23b7af8e46d4b6485d302a11673fe94c6b67ca2cfbb60c989848b02100d0594ac1 + languageName: node + linkType: hard + +"p-limit@npm:^3.0.2": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: ^0.1.0 + checksum: 7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360 + languageName: node + linkType: hard + +"p-limit@npm:^4.0.0": + version: 4.0.0 + resolution: "p-limit@npm:4.0.0" + dependencies: + yocto-queue: ^1.0.0 + checksum: 01d9d70695187788f984226e16c903475ec6a947ee7b21948d6f597bed788e3112cc7ec2e171c1d37125057a5f45f3da21d8653e04a3a793589e12e9e80e756b + languageName: node + linkType: hard + +"p-locate@npm:^2.0.0": + version: 2.0.0 + resolution: "p-locate@npm:2.0.0" + dependencies: + p-limit: ^1.1.0 + checksum: e2dceb9b49b96d5513d90f715780f6f4972f46987dc32a0e18bc6c3fc74a1a5d73ec5f81b1398af5e58b99ea1ad03fd41e9181c01fa81b4af2833958696e3081 + languageName: node + linkType: hard + +"p-locate@npm:^3.0.0": + version: 3.0.0 + resolution: "p-locate@npm:3.0.0" + dependencies: + p-limit: ^2.0.0 + checksum: 83991734a9854a05fe9dbb29f707ea8a0599391f52daac32b86f08e21415e857ffa60f0e120bfe7ce0cc4faf9274a50239c7895fc0d0579d08411e513b83a4ae + languageName: node + linkType: hard + +"p-locate@npm:^4.1.0": + version: 4.1.0 + resolution: "p-locate@npm:4.1.0" + dependencies: + p-limit: ^2.2.0 + checksum: 513bd14a455f5da4ebfcb819ef706c54adb09097703de6aeaa5d26fe5ea16df92b48d1ac45e01e3944ce1e6aa2a66f7f8894742b8c9d6e276e16cd2049a2b870 + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: ^3.0.2 + checksum: 1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3 + languageName: node + linkType: hard + +"p-locate@npm:^6.0.0": + version: 6.0.0 + resolution: "p-locate@npm:6.0.0" + dependencies: + p-limit: ^4.0.0 + checksum: 2bfe5234efa5e7a4e74b30a5479a193fdd9236f8f6b4d2f3f69e3d286d9a7d7ab0c118a2a50142efcf4e41625def635bd9332d6cbf9cc65d85eb0718c579ab38 + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: ^3.0.0 + checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c + languageName: node + linkType: hard + +"p-retry@npm:^4.5.0": + version: 4.6.2 + resolution: "p-retry@npm:4.6.2" + dependencies: + "@types/retry": 0.12.0 + retry: ^0.13.1 + checksum: 45c270bfddaffb4a895cea16cb760dcc72bdecb6cb45fef1971fa6ea2e91ddeafddefe01e444ac73e33b1b3d5d29fb0dd18a7effb294262437221ddc03ce0f2e + languageName: node + linkType: hard + +"p-retry@npm:^6.2.0": + version: 6.2.0 + resolution: "p-retry@npm:6.2.0" + dependencies: + "@types/retry": 0.12.2 + is-network-error: ^1.0.0 + retry: ^0.13.1 + checksum: 6003573c559ee812329c9c3ede7ba12a783fdc8dd70602116646e850c920b4597dc502fe001c3f9526fca4e93275045db7a27341c458e51db179c1374a01ac44 + languageName: node + linkType: hard + +"p-try@npm:^1.0.0": + version: 1.0.0 + resolution: "p-try@npm:1.0.0" + checksum: 3b5303f77eb7722144154288bfd96f799f8ff3e2b2b39330efe38db5dd359e4fb27012464cd85cb0a76e9b7edd1b443568cb3192c22e7cffc34989df0bafd605 + languageName: node + linkType: hard + +"p-try@npm:^2.0.0": + version: 2.2.0 + resolution: "p-try@npm:2.2.0" + checksum: f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae + languageName: node + linkType: hard + +"pac-proxy-agent@npm:^7.0.1": + version: 7.0.1 + resolution: "pac-proxy-agent@npm:7.0.1" + dependencies: + "@tootallnate/quickjs-emscripten": ^0.23.0 + agent-base: ^7.0.2 + debug: ^4.3.4 + get-uri: ^6.0.1 + http-proxy-agent: ^7.0.0 + https-proxy-agent: ^7.0.2 + pac-resolver: ^7.0.0 + socks-proxy-agent: ^8.0.2 + checksum: 3d4aa48ec1c19db10158ecc1c4c9a9f77792294412d225ceb3dfa45d5a06950dca9755e2db0d9b69f12769119bea0adf2b24390d9c73c8d81df75e28245ae451 + languageName: node + linkType: hard + +"pac-resolver@npm:^7.0.0": + version: 7.0.0 + resolution: "pac-resolver@npm:7.0.0" + dependencies: + degenerator: ^5.0.0 + ip: ^1.1.8 + netmask: ^2.0.2 + checksum: fa3a898c09848e93e35f5e23443fea36ddb393a851c76a23664a5bf3fcbe58ff77a0bcdae1e4f01b9ea87ea493c52e14d97a0fe39f92474d14cd45559c6e3cde + languageName: node + linkType: hard + +"package-json@npm:^6.3.0": + version: 6.5.0 + resolution: "package-json@npm:6.5.0" + dependencies: + got: ^9.6.0 + registry-auth-token: ^4.0.0 + registry-url: ^5.0.0 + semver: ^6.2.0 + checksum: cc9f890d3667d7610e6184decf543278b87f657d1ace0deb4a9c9155feca738ef88f660c82200763d3348010f4e42e9c7adc91e96ab0f86a770955995b5351e2 + languageName: node + linkType: hard + +"package-json@npm:^8.1.0": + version: 8.1.1 + resolution: "package-json@npm:8.1.1" + dependencies: + got: ^12.1.0 + registry-auth-token: ^5.0.1 + registry-url: ^6.0.0 + semver: ^7.3.7 + checksum: 28bec6f42bf9fba66b7c8fea07576fc23d08ec7923433f7835d6cd8654e72169d74f9738b3785107d18a476ae76712e0daeb1dddcd6930e69f9e4b47eba7c0ca + languageName: node + linkType: hard + +"pako@npm:^2.1.0": + version: 2.1.0 + resolution: "pako@npm:2.1.0" + checksum: 71666548644c9a4d056bcaba849ca6fd7242c6cf1af0646d3346f3079a1c7f4a66ffec6f7369ee0dc88f61926c10d6ab05da3e1fca44b83551839e89edd75a3e + languageName: node + linkType: hard + +"param-case@npm:^3.0.4": + version: 3.0.4 + resolution: "param-case@npm:3.0.4" + dependencies: + dot-case: ^3.0.4 + tslib: ^2.0.3 + checksum: b34227fd0f794e078776eb3aa6247442056cb47761e9cd2c4c881c86d84c64205f6a56ef0d70b41ee7d77da02c3f4ed2f88e3896a8fefe08bdfb4deca037c687 + languageName: node + linkType: hard + +"parent-module@npm:^1.0.0": + version: 1.0.1 + resolution: "parent-module@npm:1.0.1" + dependencies: + callsites: ^3.0.0 + checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff + languageName: node + linkType: hard + +"parent-module@npm:^2.0.0": + version: 2.0.0 + resolution: "parent-module@npm:2.0.0" + dependencies: + callsites: ^3.1.0 + checksum: f131f13d687a938556a01033561fb1b274b39921eb4425c7a691f0d91dcfbe9b19759c2b8d425a3ee7c8a46874e57fa418a690643880c3c7c56827aba12f78dd + languageName: node + linkType: hard + +"parse-entities@npm:^2.0.0": + version: 2.0.0 + resolution: "parse-entities@npm:2.0.0" + dependencies: + character-entities: ^1.0.0 + character-entities-legacy: ^1.0.0 + character-reference-invalid: ^1.0.0 + is-alphanumerical: ^1.0.0 + is-decimal: ^1.0.0 + is-hexadecimal: ^1.0.0 + checksum: 7addfd3e7d747521afac33c8121a5f23043c6973809756920d37e806639b4898385d386fcf4b3c8e2ecf1bc28aac5ae97df0b112d5042034efbe80f44081ebce + languageName: node + linkType: hard + +"parse-entities@npm:^4.0.0": + version: 4.0.1 + resolution: "parse-entities@npm:4.0.1" + dependencies: + "@types/unist": ^2.0.0 + character-entities: ^2.0.0 + character-entities-legacy: ^3.0.0 + character-reference-invalid: ^2.0.0 + decode-named-character-reference: ^1.0.0 + is-alphanumerical: ^2.0.0 + is-decimal: ^2.0.0 + is-hexadecimal: ^2.0.0 + checksum: 32a6ff5b9acb9d2c4d71537308521fd265e685b9215691df73feedd9edfe041bb6da9f89bd0c35c4a2bc7d58e3e76e399bb6078c2fd7d2a343ff1dd46edbf1bd + languageName: node + linkType: hard + +"parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": + version: 5.2.0 + resolution: "parse-json@npm:5.2.0" + dependencies: + "@babel/code-frame": ^7.0.0 + error-ex: ^1.3.1 + json-parse-even-better-errors: ^2.3.0 + lines-and-columns: ^1.1.6 + checksum: 62085b17d64da57f40f6afc2ac1f4d95def18c4323577e1eced571db75d9ab59b297d1d10582920f84b15985cbfc6b6d450ccbf317644cfa176f3ed982ad87e2 + languageName: node + linkType: hard + +"parse-numeric-range@npm:^1.3.0": + version: 1.3.0 + resolution: "parse-numeric-range@npm:1.3.0" + checksum: 289ca126d5b8ace7325b199218de198014f58ea6895ccc88a5247491d07f0143bf047f80b4a31784f1ca8911762278d7d6ecb90a31dfae31da91cc1a2524c8ce + languageName: node + linkType: hard + +"parse5-htmlparser2-tree-adapter@npm:^7.0.0": + version: 7.0.0 + resolution: "parse5-htmlparser2-tree-adapter@npm:7.0.0" + dependencies: + domhandler: ^5.0.2 + parse5: ^7.0.0 + checksum: fc5d01e07733142a1baf81de5c2a9c41426c04b7ab29dd218acb80cd34a63177c90aff4a4aee66cf9f1d0aeecff1389adb7452ad6f8af0a5888e3e9ad6ef733d + languageName: node + linkType: hard + +"parse5@npm:^6.0.0, parse5@npm:^6.0.1": + version: 6.0.1 + resolution: "parse5@npm:6.0.1" + checksum: 7d569a176c5460897f7c8f3377eff640d54132b9be51ae8a8fa4979af940830b2b0c296ce75e5bd8f4041520aadde13170dbdec44889975f906098ea0002f4bd + languageName: node + linkType: hard + +"parse5@npm:^7.0.0": + version: 7.1.2 + resolution: "parse5@npm:7.1.2" + dependencies: + entities: ^4.4.0 + checksum: 59465dd05eb4c5ec87b76173d1c596e152a10e290b7abcda1aecf0f33be49646ea74840c69af975d7887543ea45564801736356c568d6b5e71792fd0f4055713 + languageName: node + linkType: hard + +"parseurl@npm:^1.3.2, parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 + languageName: node + linkType: hard + +"pascal-case@npm:^3.1.2": + version: 3.1.2 + resolution: "pascal-case@npm:3.1.2" + dependencies: + no-case: ^3.0.4 + tslib: ^2.0.3 + checksum: ba98bfd595fc91ef3d30f4243b1aee2f6ec41c53b4546bfa3039487c367abaa182471dcfc830a1f9e1a0df00c14a370514fa2b3a1aacc68b15a460c31116873e + languageName: node + linkType: hard + +"path-browserify@npm:^1.0.1": + version: 1.0.1 + resolution: "path-browserify@npm:1.0.1" + checksum: c6d7fa376423fe35b95b2d67990060c3ee304fc815ff0a2dc1c6c3cfaff2bd0d572ee67e18f19d0ea3bbe32e8add2a05021132ac40509416459fffee35200699 + languageName: node + linkType: hard + +"path-exists@npm:^3.0.0": + version: 3.0.0 + resolution: "path-exists@npm:3.0.0" + checksum: 96e92643aa34b4b28d0de1cd2eba52a1c5313a90c6542d03f62750d82480e20bfa62bc865d5cfc6165f5fcd5aeb0851043c40a39be5989646f223300021bae0a + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 + languageName: node + linkType: hard + +"path-exists@npm:^5.0.0": + version: 5.0.0 + resolution: "path-exists@npm:5.0.0" + checksum: 8ca842868cab09423994596eb2c5ec2a971c17d1a3cb36dbf060592c730c725cd524b9067d7d2a1e031fef9ba7bd2ac6dc5ec9fb92aa693265f7be3987045254 + languageName: node + linkType: hard + +"path-is-absolute@npm:1.0.1, path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 + languageName: node + linkType: hard + +"path-is-inside@npm:1.0.2": + version: 1.0.2 + resolution: "path-is-inside@npm:1.0.2" + checksum: 0b5b6c92d3018b82afb1f74fe6de6338c4c654de4a96123cb343f2b747d5606590ac0c890f956ed38220a4ab59baddfd7b713d78a62d240b20b14ab801fa02cb + languageName: node + linkType: hard + +"path-key@npm:^3.0.0, path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 + 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" + checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a + languageName: node + linkType: hard + +"path-scurry@npm:^1.10.1": + version: 1.10.1 + resolution: "path-scurry@npm:1.10.1" + dependencies: + lru-cache: ^9.1.1 || ^10.0.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 + languageName: node + linkType: hard + +"path-to-regexp@npm:0.1.7": + version: 0.1.7 + resolution: "path-to-regexp@npm:0.1.7" + checksum: 69a14ea24db543e8b0f4353305c5eac6907917031340e5a8b37df688e52accd09e3cebfe1660b70d76b6bd89152f52183f28c74813dbf454ba1a01c82a38abce + languageName: node + linkType: hard + +"path-to-regexp@npm:2.2.1": + version: 2.2.1 + resolution: "path-to-regexp@npm:2.2.1" + checksum: b921a74e7576e25b06ad1635abf7e8125a29220d2efc2b71d74b9591f24a27e6f09078fa9a1b27516a097ea0637b7cab79d19b83d7f36a8ef3ef5422770e89d9 + languageName: node + linkType: hard + +"path-to-regexp@npm:^1.7.0": + version: 1.8.0 + resolution: "path-to-regexp@npm:1.8.0" + dependencies: + isarray: 0.0.1 + checksum: 709f6f083c0552514ef4780cb2e7e4cf49b0cc89a97439f2b7cc69a608982b7690fb5d1720a7473a59806508fc2dae0be751ba49f495ecf89fd8fbc62abccbcd + languageName: node + linkType: hard + +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 + languageName: node + linkType: hard + +"path-type@npm:^5.0.0": + version: 5.0.0 + resolution: "path-type@npm:5.0.0" + checksum: 15ec24050e8932c2c98d085b72cfa0d6b4eeb4cbde151a0a05726d8afae85784fc5544f733d8dfc68536587d5143d29c0bd793623fad03d7e61cc00067291cd5 + languageName: node + linkType: hard + +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: 090e3147716647fb7fb5b4b8c8e5b55e5d0a6086d085b6cd23f3d3c01fcf0ff56fd3cc22f2f4a033bd2e46ed55d61ed8379e123b42afe7d531a2a5fc8bb556d6 + languageName: node + linkType: hard + +"pbkdf2@npm:^3.0.17": + version: 3.1.2 + resolution: "pbkdf2@npm:3.1.2" + dependencies: + create-hash: ^1.1.2 + create-hmac: ^1.1.4 + ripemd160: ^2.0.1 + safe-buffer: ^5.0.1 + sha.js: ^2.4.8 + checksum: 2c950a100b1da72123449208e231afc188d980177d021d7121e96a2de7f2abbc96ead2b87d03d8fe5c318face097f203270d7e27908af9f471c165a4e8e69c92 + languageName: node + linkType: hard + +"pend@npm:~1.2.0": + version: 1.2.0 + resolution: "pend@npm:1.2.0" + checksum: 6c72f5243303d9c60bd98e6446ba7d30ae29e3d56fdb6fae8767e8ba6386f33ee284c97efe3230a0d0217e2b1723b8ab490b1bbf34fcbb2180dbc8a9de47850d + languageName: node + linkType: hard + +"periscopic@npm:^3.0.0": + version: 3.1.0 + resolution: "periscopic@npm:3.1.0" + dependencies: + "@types/estree": ^1.0.0 + estree-walker: ^3.0.0 + is-reference: ^3.0.0 + checksum: 2153244352e58a0d76e7e8d9263e66fe74509495f809af388da20045fb30aa3e93f2f94468dc0b9166ecf206fcfc0d73d2c7641c6fbedc07b1de858b710142cb + languageName: node + linkType: hard + +"picocolors@npm:^1.0.0": + version: 1.0.0 + resolution: "picocolors@npm:1.0.0" + checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 + languageName: node + linkType: hard + +"picocolors@npm:^1.0.1, picocolors@npm:^1.1.0": + version: 1.1.0 + resolution: "picocolors@npm:1.1.0" + checksum: a64d653d3a188119ff45781dfcdaeedd7625583f45280aea33fcb032c7a0d3959f2368f9b192ad5e8aade75b74dbd954ffe3106c158509a45e4c18ab379a2acd + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.2, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf + languageName: node + linkType: hard + +"pkg-dir@npm:^4.1.0, pkg-dir@npm:^4.2.0": + version: 4.2.0 + resolution: "pkg-dir@npm:4.2.0" + dependencies: + find-up: ^4.0.0 + checksum: 9863e3f35132bf99ae1636d31ff1e1e3501251d480336edb1c211133c8d58906bed80f154a1d723652df1fda91e01c7442c2eeaf9dc83157c7ae89087e43c8d6 + languageName: node + linkType: hard + +"pkg-dir@npm:^7.0.0": + version: 7.0.0 + resolution: "pkg-dir@npm:7.0.0" + dependencies: + find-up: ^6.3.0 + checksum: 94298b20a446bfbbd66604474de8a0cdd3b8d251225170970f15d9646f633e056c80520dd5b4c1d1050c9fed8f6a9e5054b141c93806439452efe72e57562c03 + languageName: node + linkType: hard + +"pkg-up@npm:^3.1.0": + version: 3.1.0 + resolution: "pkg-up@npm:3.1.0" + dependencies: + find-up: ^3.0.0 + checksum: 5bac346b7c7c903613c057ae3ab722f320716199d753f4a7d053d38f2b5955460f3e6ab73b4762c62fd3e947f58e04f1343e92089e7bb6091c90877406fcd8c8 + languageName: node + linkType: hard + +"playwright-core@npm:1.42.1": + version: 1.42.1 + resolution: "playwright-core@npm:1.42.1" + bin: + playwright-core: cli.js + checksum: e7081ff0f43b4b9053255109eb1d82164b7c6b55c7d022e25fca935d0f4fc547cb2e02a7b64f0c2a9462729be7bb45edb082f8b038306415944f1061d00d9c90 + languageName: node + linkType: hard + +"playwright@npm:^1.22.2": + version: 1.42.1 + resolution: "playwright@npm:1.42.1" + dependencies: + fsevents: 2.3.2 + playwright-core: 1.42.1 + dependenciesMeta: + fsevents: + optional: true + bin: + playwright: cli.js + checksum: 06c16bcd07d03993126ee6c168bde28c59d3cab7f7d4721eaf57bd5c51e9c929e10a286758de062b5fc02874413ceae2684d14cbb7865c0a51fc8df6d9001ad1 + languageName: node + linkType: hard + +"portfinder@npm:^1.0.32": + version: 1.0.32 + resolution: "portfinder@npm:1.0.32" + dependencies: + async: ^2.6.4 + debug: ^3.2.7 + mkdirp: ^0.5.6 + checksum: 116b4aed1b9e16f6d5503823d966d9ffd41b1c2339e27f54c06cd2f3015a9d8ef53e2a53b57bc0a25af0885977b692007353aa28f9a0a98a44335cb50487240d + languageName: node + linkType: hard + +"postcss-calc@npm:^8.2.3": + version: 8.2.4 + resolution: "postcss-calc@npm:8.2.4" + dependencies: + postcss-selector-parser: ^6.0.9 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.2 + checksum: 314b4cebb0c4ed0cf8356b4bce71eca78f5a7842e6a3942a3bba49db168d5296b2bd93c3f735ae1c616f2651d94719ade33becc03c73d2d79c7394fb7f73eabb + languageName: node + linkType: hard + +"postcss-calc@npm:^9.0.1": + version: 9.0.1 + resolution: "postcss-calc@npm:9.0.1" + dependencies: + postcss-selector-parser: ^6.0.11 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.2 + checksum: 7327ed83bfec544ab8b3e38353baa72ff6d04378b856db4ad82dbd68ce0b73668867ef182b5d4025f9dd9aa9c64aacc50cd1bd9db8d8b51ccc4cb97866b9d72b + languageName: node + linkType: hard + +"postcss-colormin@npm:^5.3.1": + version: 5.3.1 + resolution: "postcss-colormin@npm:5.3.1" + dependencies: + browserslist: ^4.21.4 + caniuse-api: ^3.0.0 + colord: ^2.9.1 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: e5778baab30877cd1f51e7dc9d2242a162aeca6360a52956acd7f668c5bc235c2ccb7e4df0370a804d65ebe00c5642366f061db53aa823f9ed99972cebd16024 + languageName: node + linkType: hard + +"postcss-colormin@npm:^6.1.0": + version: 6.1.0 + resolution: "postcss-colormin@npm:6.1.0" + dependencies: + browserslist: ^4.23.0 + caniuse-api: ^3.0.0 + colord: ^2.9.3 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 55a1525de345d953bc7f32ecaa5ee6275ef0277c27d1f97ff06a1bd1a2fedf7f254e36dc1500621f1df20c25a6d2485a74a0b527d8ff74eb90726c76efe2ac8e + languageName: node + linkType: hard + +"postcss-convert-values@npm:^5.1.3": + version: 5.1.3 + resolution: "postcss-convert-values@npm:5.1.3" + dependencies: + browserslist: ^4.21.4 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: df48cdaffabf9737f9cfdc58a3dc2841cf282506a7a944f6c70236cff295d3a69f63de6e0935eeb8a9d3f504324e5b4e240abc29e21df9e35a02585d3060aeb5 + languageName: node + linkType: hard + +"postcss-convert-values@npm:^6.1.0": + version: 6.1.0 + resolution: "postcss-convert-values@npm:6.1.0" + dependencies: + browserslist: ^4.23.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 43e9f66af9bdec3c76695f9dde36885abc01f662c370c490b45d895459caab2c5792f906f3ddad107129133e41485a65634da7f699eef916a636e47f6a37a299 + languageName: node + linkType: hard + +"postcss-discard-comments@npm:^5.1.2": + version: 5.1.2 + resolution: "postcss-discard-comments@npm:5.1.2" + peerDependencies: + postcss: ^8.2.15 + checksum: abfd064ebc27aeaf5037643dd51ffaff74d1fa4db56b0523d073ace4248cbb64ffd9787bd6924b0983a9d0bd0e9bf9f10d73b120e50391dc236e0d26c812fa2a + languageName: node + linkType: hard + +"postcss-discard-comments@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-discard-comments@npm:6.0.2" + peerDependencies: + postcss: ^8.4.31 + checksum: c1731ccc8d1e3d910412a61395988d3033365e6532d9e5432ad7c74add8c9dcb0af0c03d4e901bf0d2b59ea4e7297a0c77a547ff2ed1b1cc065559cc0de43b4e + languageName: node + linkType: hard + +"postcss-discard-duplicates@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-discard-duplicates@npm:5.1.0" + peerDependencies: + postcss: ^8.2.15 + checksum: 88d6964201b1f4ed6bf7a32cefe68e86258bb6e42316ca01d9b32bdb18e7887d02594f89f4a2711d01b51ea6e3fcca8c54be18a59770fe5f4521c61d3eb6ca35 + languageName: node + linkType: hard + +"postcss-discard-duplicates@npm:^6.0.3": + version: 6.0.3 + resolution: "postcss-discard-duplicates@npm:6.0.3" + peerDependencies: + postcss: ^8.4.31 + checksum: 308e3fb84c35e4703532de1efa5d6e8444cc5f167d0e40f42d7ea3fa3a37d9d636fd10729847d078e0c303eee16f8548d14b6f88a3fce4e38a2b452648465175 + languageName: node + linkType: hard + +"postcss-discard-empty@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-discard-empty@npm:5.1.1" + peerDependencies: + postcss: ^8.2.15 + checksum: 970adb12fae5c214c0768236ad9a821552626e77dedbf24a8213d19cc2c4a531a757cd3b8cdd3fc22fb1742471b8692a1db5efe436a71236dec12b1318ee8ff4 + languageName: node + linkType: hard + +"postcss-discard-empty@npm:^6.0.3": + version: 6.0.3 + resolution: "postcss-discard-empty@npm:6.0.3" + peerDependencies: + postcss: ^8.4.31 + checksum: bad305572faa066026a295faab37e718cee096589ab827b19c990c55620b2b2a1ce9f0145212651737a66086db01b2676c1927bbb8408c5f9cb42686d5959f00 + languageName: node + linkType: hard + +"postcss-discard-overridden@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-discard-overridden@npm:5.1.0" + peerDependencies: + postcss: ^8.2.15 + checksum: d64d4a545aa2c81b22542895cfcddc787d24119f294d35d29b0599a1c818b3cc51f4ee80b80f5a0a09db282453dd5ac49f104c2117cc09112d0ac9b40b499a41 + languageName: node + linkType: hard + +"postcss-discard-overridden@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-discard-overridden@npm:6.0.2" + peerDependencies: + postcss: ^8.4.31 + checksum: a38e0fe7a36f83cb9b73c1ba9ee2a48cf93c69ec0ea5753935824ffb71e958e58ae0393171c0f3d0014a397469d09bbb0d56bb5ab80f0280722967e2e273aebb + languageName: node + linkType: hard + +"postcss-discard-unused@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-discard-unused@npm:5.1.0" + dependencies: + postcss-selector-parser: ^6.0.5 + peerDependencies: + postcss: ^8.2.15 + checksum: 5c09403a342a065033f5f22cefe6b402c76c2dc0aac31a736a2062d82c2a09f0ff2525b3df3a0c6f4e0ffc7a0392efd44bfe7f9d018e4cae30d15b818b216622 + languageName: node + linkType: hard + +"postcss-discard-unused@npm:^6.0.5": + version: 6.0.5 + resolution: "postcss-discard-unused@npm:6.0.5" + dependencies: + postcss-selector-parser: ^6.0.16 + peerDependencies: + postcss: ^8.4.31 + checksum: 7962640773240186de38125f142a6555b7f9b2493c4968e0f0b11c6629b2bf43ac70b9fc4ee78aa732d82670ad8bf802b2febc9a9864b022eb68530eded26836 + languageName: node + linkType: hard + +"postcss-loader@npm:^7.0.0, postcss-loader@npm:^7.3.3": + version: 7.3.3 + resolution: "postcss-loader@npm:7.3.3" + dependencies: + cosmiconfig: ^8.2.0 + jiti: ^1.18.2 + semver: ^7.3.8 + peerDependencies: + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + checksum: c724044d6ae56334535c26bb4efc9c151431d44d60bc8300157c760747281a242757d8dab32db72738434531175b38a408cb0b270bb96207c07584dcfcd899ff + languageName: node + linkType: hard + +"postcss-merge-idents@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-merge-idents@npm:5.1.1" + dependencies: + cssnano-utils: ^3.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: ed8a673617ea6ae3e15d69558063cb1a5eeee01732f78cdc0196ab910324abc30828724ab8dfc4cda27e8c0077542e25688470f829819a2604625a673387ec72 + languageName: node + linkType: hard + +"postcss-merge-idents@npm:^6.0.3": + version: 6.0.3 + resolution: "postcss-merge-idents@npm:6.0.3" + dependencies: + cssnano-utils: ^4.0.2 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: b45780d6d103b8e45a580032747ee6e1842f81863672341a6b4961397e243ca896217bf1f3ee732376a766207d5f610ba8924cf08cf6d5bbd4b093133fd05d70 + languageName: node + linkType: hard + +"postcss-merge-longhand@npm:^5.1.7": + version: 5.1.7 + resolution: "postcss-merge-longhand@npm:5.1.7" + dependencies: + postcss-value-parser: ^4.2.0 + stylehacks: ^5.1.1 + peerDependencies: + postcss: ^8.2.15 + checksum: 81c3fc809f001b9b71a940148e242bdd6e2d77713d1bfffa15eb25c1f06f6648d5e57cb21645746d020a2a55ff31e1740d2b27900442913a9d53d8a01fb37e1b + languageName: node + linkType: hard + +"postcss-merge-longhand@npm:^6.0.5": + version: 6.0.5 + resolution: "postcss-merge-longhand@npm:6.0.5" + dependencies: + postcss-value-parser: ^4.2.0 + stylehacks: ^6.1.1 + peerDependencies: + postcss: ^8.4.31 + checksum: 9ae5acf47dc0c1f494684ae55672d55bba7f5ee11c9c0f266aabd7c798e9f7394c6096363cd95685fd21ef088740389121a317772cf523ca22c915009bca2617 + languageName: node + linkType: hard + +"postcss-merge-rules@npm:^5.1.4": + version: 5.1.4 + resolution: "postcss-merge-rules@npm:5.1.4" + dependencies: + browserslist: ^4.21.4 + caniuse-api: ^3.0.0 + cssnano-utils: ^3.1.0 + postcss-selector-parser: ^6.0.5 + peerDependencies: + postcss: ^8.2.15 + checksum: 8ab6a569babe6cb412d6612adee74f053cea7edb91fa013398515ab36754b1fec830d68782ed8cdfb44cffdc6b78c79eab157bff650f428aa4460d3f3857447e + languageName: node + linkType: hard + +"postcss-merge-rules@npm:^6.1.1": + version: 6.1.1 + resolution: "postcss-merge-rules@npm:6.1.1" + dependencies: + browserslist: ^4.23.0 + caniuse-api: ^3.0.0 + cssnano-utils: ^4.0.2 + postcss-selector-parser: ^6.0.16 + peerDependencies: + postcss: ^8.4.31 + checksum: 43f60a1c88806491cf752ae7871676de0e7a2a9d6d2fc6bc894068cc35a910a63d30f7c7d79545e0926c8b3a9ec583e5e8357203c40b5bad5ff58133b0c900f6 + languageName: node + linkType: hard + +"postcss-minify-font-values@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-minify-font-values@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 35e858fa41efa05acdeb28f1c76579c409fdc7eabb1744c3bd76e895bb9fea341a016746362a67609688ab2471f587202b9a3e14ea28ad677754d663a2777ece + languageName: node + linkType: hard + +"postcss-minify-font-values@npm:^6.1.0": + version: 6.1.0 + resolution: "postcss-minify-font-values@npm:6.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 985e4dd2f89220a4442a822aad7dff016ab58a9dbb7bbca9d01c2d07d5a1e7d8c02e1c6e836abb4c9b4e825b4b80d99ee1f5899e74bf0d969095037738e6e452 + languageName: node + linkType: hard + +"postcss-minify-gradients@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-minify-gradients@npm:5.1.1" + dependencies: + colord: ^2.9.1 + cssnano-utils: ^3.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 27354072a07c5e6dab36731103b94ca2354d4ed3c5bc6aacfdf2ede5a55fa324679d8fee5450800bc50888dbb5e9ed67569c0012040c2be128143d0cebb36d67 + languageName: node + linkType: hard + +"postcss-minify-gradients@npm:^6.0.3": + version: 6.0.3 + resolution: "postcss-minify-gradients@npm:6.0.3" + dependencies: + colord: ^2.9.3 + cssnano-utils: ^4.0.2 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 89b95088c3830f829f6d4636d1be4d4f13300bf9f1577c48c25169c81e11ec0026760b9abb32112b95d2c622f09d3b737f4d2975a7842927ccb567e1002ef7b3 + languageName: node + linkType: hard + +"postcss-minify-params@npm:^5.1.4": + version: 5.1.4 + resolution: "postcss-minify-params@npm:5.1.4" + dependencies: + browserslist: ^4.21.4 + cssnano-utils: ^3.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: bd63e2cc89edcf357bb5c2a16035f6d02ef676b8cede4213b2bddd42626b3d428403849188f95576fc9f03e43ebd73a29bf61d33a581be9a510b13b7f7f100d5 + languageName: node + linkType: hard + +"postcss-minify-params@npm:^6.1.0": + version: 6.1.0 + resolution: "postcss-minify-params@npm:6.1.0" + dependencies: + browserslist: ^4.23.0 + cssnano-utils: ^4.0.2 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 1e1cc3057d9bcc532c70e40628e96e3aea0081d8072dffe983a270a8cd59c03ac585e57d036b70e43d4ee725f274a05a6a8efac5a715f448284e115c13f82a46 + languageName: node + linkType: hard + +"postcss-minify-selectors@npm:^5.2.1": + version: 5.2.1 + resolution: "postcss-minify-selectors@npm:5.2.1" + dependencies: + postcss-selector-parser: ^6.0.5 + peerDependencies: + postcss: ^8.2.15 + checksum: 6fdbc84f99a60d56b43df8930707da397775e4c36062a106aea2fd2ac81b5e24e584a1892f4baa4469fa495cb87d1422560eaa8f6c9d500f9f0b691a5f95bab5 + languageName: node + linkType: hard + +"postcss-minify-selectors@npm:^6.0.4": + version: 6.0.4 + resolution: "postcss-minify-selectors@npm:6.0.4" + dependencies: + postcss-selector-parser: ^6.0.16 + peerDependencies: + postcss: ^8.4.31 + checksum: 150221a84422ca7627c67ee691ee51e0fe2c3583c8108801e9fc93d3be8b538c2eb04fcfdc908270d7eeaeaf01594a20b81311690a873efccb8a23aeafe1c354 + languageName: node + linkType: hard + +"postcss-modules-extract-imports@npm:^3.0.0": + version: 3.0.0 + resolution: "postcss-modules-extract-imports@npm:3.0.0" + peerDependencies: + postcss: ^8.1.0 + checksum: 4b65f2f1382d89c4bc3c0a1bdc5942f52f3cb19c110c57bd591ffab3a5fee03fcf831604168205b0c1b631a3dce2255c70b61aaae3ef39d69cd7eb450c2552d2 + languageName: node + linkType: hard + +"postcss-modules-local-by-default@npm:^4.0.3": + version: 4.0.3 + resolution: "postcss-modules-local-by-default@npm:4.0.3" + dependencies: + icss-utils: ^5.0.0 + postcss-selector-parser: ^6.0.2 + postcss-value-parser: ^4.1.0 + peerDependencies: + postcss: ^8.1.0 + checksum: 2f8083687f3d6067885f8863dd32dbbb4f779cfcc7e52c17abede9311d84faf6d3ed8760e7c54c6380281732ae1f78e5e56a28baf3c271b33f450a11c9e30485 + languageName: node + linkType: hard + +"postcss-modules-scope@npm:^3.0.0": + version: 3.0.0 + resolution: "postcss-modules-scope@npm:3.0.0" + dependencies: + postcss-selector-parser: ^6.0.4 + peerDependencies: + postcss: ^8.1.0 + checksum: 330b9398dbd44c992c92b0dc612c0626135e2cc840fee41841eb61247a6cfed95af2bd6f67ead9dd9d0bb41f5b0367129d93c6e434fa3e9c58ade391d9a5a138 + languageName: node + linkType: hard + +"postcss-modules-values@npm:^4.0.0": + version: 4.0.0 + resolution: "postcss-modules-values@npm:4.0.0" + dependencies: + icss-utils: ^5.0.0 + peerDependencies: + postcss: ^8.1.0 + checksum: f7f2cdf14a575b60e919ad5ea52fed48da46fe80db2733318d71d523fc87db66c835814940d7d05b5746b0426e44661c707f09bdb83592c16aea06e859409db6 + languageName: node + linkType: hard + +"postcss-normalize-charset@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-charset@npm:5.1.0" + peerDependencies: + postcss: ^8.2.15 + checksum: e79d92971fc05b8b3c9b72f3535a574e077d13c69bef68156a0965f397fdf157de670da72b797f57b0e3bac8f38155b5dd1735ecab143b9cc4032d72138193b4 + languageName: node + linkType: hard + +"postcss-normalize-charset@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-normalize-charset@npm:6.0.2" + peerDependencies: + postcss: ^8.4.31 + checksum: 5b8aeb17d61578a8656571cd5d5eefa8d4ee7126a99a41fdd322078002a06f2ae96f649197b9c01067a5f3e38a2e4b03e0e3fda5a0ec9e3d7ad056211ce86156 + languageName: node + linkType: hard + +"postcss-normalize-display-values@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-display-values@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: b6eb7b9b02c3bdd62bbc54e01e2b59733d73a1c156905d238e178762962efe0c6f5104544da39f32cade8a4fb40f10ff54b63a8ebfbdff51e8780afb9fbdcf86 + languageName: node + linkType: hard + +"postcss-normalize-display-values@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-normalize-display-values@npm:6.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: da30a9394b0e4a269ccad8d240693a6cd564bcc60e24db67caee00f70ddfbc070ad76faed64c32e6eec9ed02e92565488b7879d4fd6c40d877c290eadbb0bb28 + languageName: node + linkType: hard + +"postcss-normalize-positions@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-normalize-positions@npm:5.1.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: d9afc233729c496463c7b1cdd06732469f401deb387484c3a2422125b46ec10b4af794c101f8c023af56f01970b72b535e88373b9058ecccbbf88db81662b3c4 + languageName: node + linkType: hard + +"postcss-normalize-positions@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-normalize-positions@npm:6.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 44fb77583fae4d71b76e38226cf770570876bcf5af6940dc9aeac7a7e2252896b361e0249044766cff8dad445f925378f06a005d6541597573c20e599a62b516 + languageName: node + linkType: hard + +"postcss-normalize-repeat-style@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-normalize-repeat-style@npm:5.1.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 2c6ad2b0ae10a1fda156b948c34f78c8f1e185513593de4d7e2480973586675520edfec427645fa168c337b0a6b3ceca26f92b96149741ca98a9806dad30d534 + languageName: node + linkType: hard + +"postcss-normalize-repeat-style@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-normalize-repeat-style@npm:6.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: bebdac63bec6777ead3e265fc12527b261cf8d0da1b7f0abb12bda86fd53b7058e4afe392210ac74dac012e413bb1c2a46a1138c89f82b8bf70b81711f620f8c + languageName: node + linkType: hard + +"postcss-normalize-string@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-string@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 6e549c6e5b2831e34c7bdd46d8419e2278f6af1d5eef6d26884a37c162844e60339340c57e5e06058cdbe32f27fc6258eef233e811ed2f71168ef2229c236ada + languageName: node + linkType: hard + +"postcss-normalize-string@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-normalize-string@npm:6.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 5e8e253c528b542accafc142846fb33643c342a787c86e5b68c6287c7d8f63c5ae7d4d3fc28e3daf80821cc26a91add135e58bdd62ff9c735fca65d994898c7d + languageName: node + linkType: hard + +"postcss-normalize-timing-functions@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-timing-functions@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: da550f50e90b0b23e17b67449a7d1efd1aa68288e66d4aa7614ca6f5cc012896be1972b7168eee673d27da36504faccf7b9f835c0f7e81243f966a42c8c030aa + languageName: node + linkType: hard + +"postcss-normalize-timing-functions@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-normalize-timing-functions@npm:6.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 1970f5aad04be11f99d51c59e27debb6fd7b49d0fa4a8879062b42c82113f8e520a284448727add3b54de85deefb8bd5fe554f618406586e9ad8fc9d060609f1 + languageName: node + linkType: hard + +"postcss-normalize-unicode@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-normalize-unicode@npm:5.1.1" + dependencies: + browserslist: ^4.21.4 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 4c24d26cc9f4b19a9397db4e71dd600dab690f1de8e14a3809e2aa1452dbc3791c208c38a6316bbc142f29e934fdf02858e68c94038c06174d78a4937e0f273c + languageName: node + linkType: hard + +"postcss-normalize-unicode@npm:^6.1.0": + version: 6.1.0 + resolution: "postcss-normalize-unicode@npm:6.1.0" + dependencies: + browserslist: ^4.23.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 69ef35d06242061f0c504c128b83752e0f8daa30ebb26734de7d090460910be0b2efd8b17b1d64c3c85b95831a041faad9ad0aaba80e239406a79cfad3d63568 + languageName: node + linkType: hard + +"postcss-normalize-url@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-normalize-url@npm:5.1.0" + dependencies: + normalize-url: ^6.0.1 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 3bd4b3246d6600230bc827d1760b24cb3101827ec97570e3016cbe04dc0dd28f4dbe763245d1b9d476e182c843008fbea80823061f1d2219b96f0d5c724a24c0 + languageName: node + linkType: hard + +"postcss-normalize-url@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-normalize-url@npm:6.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: bef51a18bbfee4fbf0381fec3c91e6c0dace36fca053bbd5f228e653d2732b6df3985525d79c4f7fc89f840ed07eb6d226e9d7503ecdc6f16d6d80cacae9df33 + languageName: node + linkType: hard + +"postcss-normalize-whitespace@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-normalize-whitespace@npm:5.1.1" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 12d8fb6d1c1cba208cc08c1830959b7d7ad447c3f5581873f7e185f99a9a4230c43d3af21ca12c818e4690a5085a95b01635b762ad4a7bef69d642609b4c0e19 + languageName: node + linkType: hard + +"postcss-normalize-whitespace@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-normalize-whitespace@npm:6.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 6081eb3a4b305749eec02c00a95c2d236336a77ee636bb1d939f18d5dfa5ba82b7cf7fa072e83f9133d0bc984276596af3fe468bdd67c742ce69e9c63dbc218d + languageName: node + linkType: hard + +"postcss-ordered-values@npm:^5.1.3": + version: 5.1.3 + resolution: "postcss-ordered-values@npm:5.1.3" + dependencies: + cssnano-utils: ^3.1.0 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 6f3ca85b6ceffc68aadaf319d9ee4c5ac16d93195bf8cba2d1559b631555ad61941461cda6d3909faab86e52389846b2b36345cff8f0c3f4eb345b1b8efadcf9 + languageName: node + linkType: hard + +"postcss-ordered-values@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-ordered-values@npm:6.0.2" + dependencies: + cssnano-utils: ^4.0.2 + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: c3d96177b4ffa43754e835e30c40043cc75ab1e95eb6c55ac8723eb48c13a12e986250e63d96619bbbd1a098876a1c0c1b3b7a8e1de1108a009cf7aa0beac834 + languageName: node + linkType: hard + +"postcss-reduce-idents@npm:^5.2.0": + version: 5.2.0 + resolution: "postcss-reduce-idents@npm:5.2.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: f0d644c86e160dd36ee4dd924ab7d6feacac867c87702e2f98f96b409430a62de4fec2dfc3c8731bda4e14196e29a752b4558942f0af2a3e6cd7f1f4b173db8e + languageName: node + linkType: hard + +"postcss-reduce-idents@npm:^6.0.3": + version: 6.0.3 + resolution: "postcss-reduce-idents@npm:6.0.3" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 1feff316838f947386c908f50807cf1b9589fd09b8e8df633a01f2640af5492833cc892448938ceba10ab96826c44767b8f2e1569d587579423f2db81202f7c7 + languageName: node + linkType: hard + +"postcss-reduce-initial@npm:^5.1.2": + version: 5.1.2 + resolution: "postcss-reduce-initial@npm:5.1.2" + dependencies: + browserslist: ^4.21.4 + caniuse-api: ^3.0.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 55db697f85231a81f1969d54c894e4773912d9ddb914f9b03d2e73abc4030f2e3bef4d7465756d0c1acfcc2c2d69974bfb50a972ab27546a7d68b5a4fc90282b + languageName: node + linkType: hard + +"postcss-reduce-initial@npm:^6.1.0": + version: 6.1.0 + resolution: "postcss-reduce-initial@npm:6.1.0" + dependencies: + browserslist: ^4.23.0 + caniuse-api: ^3.0.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 39e4034ffbf62a041b66944c5cebc4b17f656e76b97568f7f6230b0b886479e5c75b02ae4ba48c472cb0bde47489f9ed1fe6110ae8cff0d7b7165f53c2d64a12 + languageName: node + linkType: hard + +"postcss-reduce-transforms@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-reduce-transforms@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.2.15 + checksum: 0c6af2cba20e3ff63eb9ad045e634ddfb9c3e5c0e614c020db2a02f3aa20632318c4ede9e0c995f9225d9a101e673de91c0a6e10bb2fa5da6d6c75d15a55882f + languageName: node + linkType: hard + +"postcss-reduce-transforms@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-reduce-transforms@npm:6.0.2" + dependencies: + postcss-value-parser: ^4.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: c424cc554eb5d253b7687b64925a13fc16759f058795d223854f5a20d9bca641b5f25d0559d03287e63f07a4629c24ac78156adcf604483fcad3c51721da0a08 + languageName: node + linkType: hard + +"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.16": + version: 6.1.2 + resolution: "postcss-selector-parser@npm:6.1.2" + dependencies: + cssesc: ^3.0.0 + util-deprecate: ^1.0.2 + checksum: ce9440fc42a5419d103f4c7c1847cb75488f3ac9cbe81093b408ee9701193a509f664b4d10a2b4d82c694ee7495e022f8f482d254f92b7ffd9ed9dea696c6f84 + languageName: node + linkType: hard + +"postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4, postcss-selector-parser@npm:^6.0.5, postcss-selector-parser@npm:^6.0.9": + version: 6.0.13 + resolution: "postcss-selector-parser@npm:6.0.13" + dependencies: + cssesc: ^3.0.0 + util-deprecate: ^1.0.2 + checksum: f89163338a1ce3b8ece8e9055cd5a3165e79a15e1c408e18de5ad8f87796b61ec2d48a2902d179ae0c4b5de10fccd3a325a4e660596549b040bc5ad1b465f096 + languageName: node + linkType: hard + +"postcss-sort-media-queries@npm:^4.2.1": + version: 4.4.1 + resolution: "postcss-sort-media-queries@npm:4.4.1" + dependencies: + sort-css-media-queries: 2.1.0 + peerDependencies: + postcss: ^8.4.16 + checksum: 70b42e479bb1d15d8628678eefefd547d309e33e64262fe437630fe62d8e4b3adcae7f2b48ef8da9d3173576d4af109a9ffa9514573db1281deef324f5ea166f + languageName: node + linkType: hard + +"postcss-sort-media-queries@npm:^5.2.0": + version: 5.2.0 + resolution: "postcss-sort-media-queries@npm:5.2.0" + dependencies: + sort-css-media-queries: 2.2.0 + peerDependencies: + postcss: ^8.4.23 + checksum: d4a976a64b53234762cc35c06ce97c1684bd7a64ead17e84c2047676c7307945be7c005235e6aac7c4620e1f835d6ba1a7dcf018ab7fe0a47657c62c96ad9f35 + languageName: node + linkType: hard + +"postcss-svgo@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-svgo@npm:5.1.0" + dependencies: + postcss-value-parser: ^4.2.0 + svgo: ^2.7.0 + peerDependencies: + postcss: ^8.2.15 + checksum: d86eb5213d9f700cf5efe3073799b485fb7cacae0c731db3d7749c9c2b1c9bc85e95e0baeca439d699ff32ea24815fc916c4071b08f67ed8219df229ce1129bd + languageName: node + linkType: hard + +"postcss-svgo@npm:^6.0.3": + version: 6.0.3 + resolution: "postcss-svgo@npm:6.0.3" + dependencies: + postcss-value-parser: ^4.2.0 + svgo: ^3.2.0 + peerDependencies: + postcss: ^8.4.31 + checksum: 1a7d1c8dea555884a7791e28ec2c22ea92331731067584ff5a23042a0e615f88fefde04e1140f11c262a728ef9fab6851423b40b9c47f9ae05353bd3c0ff051a + languageName: node + linkType: hard + +"postcss-unique-selectors@npm:^5.1.1": + version: 5.1.1 + resolution: "postcss-unique-selectors@npm:5.1.1" + dependencies: + postcss-selector-parser: ^6.0.5 + peerDependencies: + postcss: ^8.2.15 + checksum: 637e7b786e8558265775c30400c54b6b3b24d4748923f4a39f16a65fd0e394f564ccc9f0a1d3c0e770618a7637a7502ea1d0d79f731d429cb202255253c23278 + languageName: node + linkType: hard + +"postcss-unique-selectors@npm:^6.0.4": + version: 6.0.4 + resolution: "postcss-unique-selectors@npm:6.0.4" + dependencies: + postcss-selector-parser: ^6.0.16 + peerDependencies: + postcss: ^8.4.31 + checksum: b09df9943b4e858e88b30f3d279ce867a0490df806f1f947d286b0a4e95ba923f1229c385e5bf365f4f124f1edccda41ec18ccad4ba8798d829279d6dc971203 + languageName: node + linkType: hard + +"postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0": + version: 4.2.0 + resolution: "postcss-value-parser@npm:4.2.0" + checksum: 819ffab0c9d51cf0acbabf8996dffbfafbafa57afc0e4c98db88b67f2094cb44488758f06e5da95d7036f19556a4a732525e84289a425f4f6fd8e412a9d7442f + languageName: node + linkType: hard + +"postcss-zindex@npm:^5.1.0": + version: 5.1.0 + resolution: "postcss-zindex@npm:5.1.0" + peerDependencies: + postcss: ^8.2.15 + checksum: 8581e0ee552622489dcb9fb9609a3ccc261a67a229ba91a70bd138fe102a2d04cedb14642b82b673d4cac7b559ef32574f2dafde2ff7816eecac024d231c5ead + languageName: node + linkType: hard + +"postcss-zindex@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-zindex@npm:6.0.2" + peerDependencies: + postcss: ^8.4.31 + checksum: 394119e47b0fb098dc53d1bcf71b5500ab29605fe106526b2e81290bff179174ee00a82a4d4be5a42d4ef4138e8a3d6aabeef3b06cf7cb15b851848c8585d53b + languageName: node + linkType: hard + +"postcss@npm:^8.4.14, postcss@npm:^8.4.17, postcss@npm:^8.4.21, postcss@npm:^8.4.26": + version: 8.4.32 + resolution: "postcss@npm:8.4.32" + dependencies: + nanoid: ^3.3.7 + picocolors: ^1.0.0 + source-map-js: ^1.0.2 + checksum: 220d9d0bf5d65be7ed31006c523bfb11619461d296245c1231831f90150aeb4a31eab9983ac9c5c89759a3ca8b60b3e0d098574964e1691673c3ce5c494305ae + languageName: node + linkType: hard + +"postcss@npm:^8.4.24, postcss@npm:^8.4.38": + version: 8.4.47 + resolution: "postcss@npm:8.4.47" + dependencies: + nanoid: ^3.3.7 + picocolors: ^1.1.0 + source-map-js: ^1.2.1 + checksum: f78440a9d8f97431dd2ab1ab8e1de64f12f3eff38a3d8d4a33919b96c381046a314658d2de213a5fa5eb296b656de76a3ec269fdea27f16d5ab465b916a0f52c + languageName: node + linkType: hard + +"prelude-ls@npm:^1.2.1": + version: 1.2.1 + resolution: "prelude-ls@npm:1.2.1" + checksum: cd192ec0d0a8e4c6da3bb80e4f62afe336df3f76271ac6deb0e6a36187133b6073a19e9727a1ff108cd8b9982e4768850d413baa71214dd80c7979617dca827a + languageName: node + linkType: hard + +"prepend-http@npm:^2.0.0": + version: 2.0.0 + resolution: "prepend-http@npm:2.0.0" + checksum: 7694a9525405447662c1ffd352fcb41b6410c705b739b6f4e3a3e21cf5fdede8377890088e8934436b8b17ba55365a615f153960f30877bf0d0392f9e93503ea + languageName: node + linkType: hard + +"prettier-linter-helpers@npm:^1.0.0": + version: 1.0.0 + resolution: "prettier-linter-helpers@npm:1.0.0" + dependencies: + fast-diff: ^1.1.2 + checksum: 00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392 + languageName: node + linkType: hard + +"prettier@npm:*": + version: 3.1.1 + resolution: "prettier@npm:3.1.1" + bin: + prettier: bin/prettier.cjs + checksum: e386855e3a1af86a748e16953f168be555ce66d6233f4ba54eb6449b88eb0c6b2ca79441b11eae6d28a7f9a5c96440ce50864b9d5f6356d331d39d6bb66c648e + languageName: node + linkType: hard + +"prettier@npm:3.2.5": + version: 3.2.5 + resolution: "prettier@npm:3.2.5" + bin: + prettier: bin/prettier.cjs + checksum: 2ee4e1417572372afb7a13bb446b34f20f1bf1747db77cf6ccaf57a9be005f2f15c40f903d41a6b79eec3f57fff14d32a20fb6dee1f126da48908926fe43c311 + languageName: node + linkType: hard + +"pretty-error@npm:^4.0.0": + version: 4.0.0 + resolution: "pretty-error@npm:4.0.0" + dependencies: + lodash: ^4.17.20 + renderkid: ^3.0.0 + checksum: a5b9137365690104ded6947dca2e33360bf55e62a4acd91b1b0d7baa3970e43754c628cc9e16eafbdd4e8f8bcb260a5865475d4fc17c3106ff2d61db4e72cdf3 + languageName: node + linkType: hard + +"pretty-time@npm:^1.1.0": + version: 1.1.0 + resolution: "pretty-time@npm:1.1.0" + checksum: a319e7009aadbc6cfedbd8b66861327d3a0c68bd3e8794bf5b86f62b40b01b9479c5a70c76bb368ad454acce52a1216daee460cc825766e2442c04f3a84a02c9 + languageName: node + linkType: hard + +"prism-react-renderer@npm:^2.1.0, prism-react-renderer@npm:^2.3.0": + version: 2.3.0 + resolution: "prism-react-renderer@npm:2.3.0" + dependencies: + "@types/prismjs": ^1.26.0 + clsx: ^2.0.0 + peerDependencies: + react: ">=16.0.0" + checksum: 29b24eb5015c09e1b7e3fa2941584ead6fceb5556fdfbe7c34548d96886e0b291290bda93a421aab8b26ce6aae677387aac294982d11349a050843f6dbbc7449 + languageName: node + linkType: hard + +"prismjs@npm:^1.29.0": + version: 1.29.0 + resolution: "prismjs@npm:1.29.0" + checksum: 007a8869d4456ff8049dc59404e32d5666a07d99c3b0e30a18bd3b7676dfa07d1daae9d0f407f20983865fd8da56de91d09cb08e6aa61f5bc420a27c0beeaf93 + languageName: node + linkType: hard + +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: 02b64e1b3919e63df06f836b98d3af002b5cd92655cab18b5746e37374bfb73e03b84fe305454614b34c25b485cc687a9eebdccf0242cda8fda2475dd2c97e02 + languageName: node + linkType: hard + +"process-nextick-args@npm:~2.0.0": + version: 2.0.1 + resolution: "process-nextick-args@npm:2.0.1" + checksum: 1d38588e520dab7cea67cbbe2efdd86a10cc7a074c09657635e34f035277b59fbb57d09d8638346bf7090f8e8ebc070c96fa5fd183b777fff4f5edff5e9466cf + languageName: node + linkType: hard + +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: bfcce49814f7d172a6e6a14d5fa3ac92cc3d0c3b9feb1279774708a719e19acd673995226351a082a9ae99978254e320ccda4240ddc474ba31a76c79491ca7c3 + languageName: node + linkType: hard + +"progress@npm:2.0.3": + version: 2.0.3 + resolution: "progress@npm:2.0.3" + checksum: f67403fe7b34912148d9252cb7481266a354bd99ce82c835f79070643bb3c6583d10dbcfda4d41e04bbc1d8437e9af0fb1e1f2135727878f5308682a579429b7 + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: ^2.0.2 + retry: ^0.12.0 + checksum: f96a3f6d90b92b568a26f71e966cbbc0f63ab85ea6ff6c81284dc869b41510e6cdef99b6b65f9030f0db422bf7c96652a3fff9f2e8fb4a0f069d8f4430359429 + languageName: node + linkType: hard + +"prompts@npm:^2.4.2": + version: 2.4.2 + resolution: "prompts@npm:2.4.2" + dependencies: + kleur: ^3.0.3 + sisteransi: ^1.0.5 + checksum: d8fd1fe63820be2412c13bfc5d0a01909acc1f0367e32396962e737cb2fc52d004f3302475d5ce7d18a1e8a79985f93ff04ee03007d091029c3f9104bffc007d + languageName: node + linkType: hard + +"prop-types@npm:^15.6.2, prop-types@npm:^15.7.2": + version: 15.8.1 + resolution: "prop-types@npm:15.8.1" + dependencies: + loose-envify: ^1.4.0 + object-assign: ^4.1.1 + react-is: ^16.13.1 + checksum: c056d3f1c057cb7ff8344c645450e14f088a915d078dcda795041765047fa080d38e5d626560ccaac94a4e16e3aa15f3557c1a9a8d1174530955e992c675e459 + languageName: node + linkType: hard + +"property-information@npm:^5.0.0, property-information@npm:^5.3.0": + version: 5.6.0 + resolution: "property-information@npm:5.6.0" + dependencies: + xtend: ^4.0.0 + checksum: fcf87c6542e59a8bbe31ca0b3255a4a63ac1059b01b04469680288998bcfa97f341ca989566adbb63975f4d85339030b82320c324a511532d390910d1c583893 + languageName: node + linkType: hard + +"property-information@npm:^6.0.0": + version: 6.4.0 + resolution: "property-information@npm:6.4.0" + checksum: b5aed9a40e87730995f3ceed29839f137fa73b2a4cccfb8ed72ab8bddb8881cad05c3487c4aa168d7cb49a53db8089790c9f00f59d15b8380d2bb5383cdd1f24 + languageName: node + linkType: hard + +"proto-list@npm:~1.2.1": + version: 1.2.4 + resolution: "proto-list@npm:1.2.4" + checksum: 4d4826e1713cbfa0f15124ab0ae494c91b597a3c458670c9714c36e8baddf5a6aad22842776f2f5b137f259c8533e741771445eb8df82e861eea37a6eaba03f7 + languageName: node + linkType: hard + +"proxy-addr@npm:~2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + checksum: 29c6990ce9364648255454842f06f8c46fcd124d3e6d7c5066df44662de63cdc0bad032e9bf5a3d653ff72141cc7b6019873d685708ac8210c30458ad99f2b74 + languageName: node + linkType: hard + +"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.1 + https-proxy-agent: ^7.0.3 + lru-cache: ^7.14.1 + pac-proxy-agent: ^7.0.1 + proxy-from-env: ^1.1.0 + socks-proxy-agent: ^8.0.2 + checksum: 4d3794ad5e07486298902f0a7f250d0f869fa0e92d790767ca3f793a81374ce0ab6c605f8ab8e791c4d754da96656b48d1c24cb7094bfd310a15867e4a0841d7 + languageName: node + linkType: hard + +"proxy-from-env@npm:^1.1.0": + version: 1.1.0 + resolution: "proxy-from-env@npm:1.1.0" + checksum: ed7fcc2ba0a33404958e34d95d18638249a68c430e30fcb6c478497d72739ba64ce9810a24f53a7d921d0c065e5b78e3822759800698167256b04659366ca4d4 + languageName: node + linkType: hard + +"prr@npm:~0.0.0": + version: 0.0.0 + resolution: "prr@npm:0.0.0" + checksum: 6552d9d92d9d55ec1afb8952ad80f81bbb1b4379f24ff7c506ad083ea701caf1bf6d4b092a2baeb98ec3f312c5a49d8bdf1d9b20a6db2998d05c2d52aa6a82e7 + languageName: node + linkType: hard + +"prr@npm:~1.0.1": + version: 1.0.1 + resolution: "prr@npm:1.0.1" + checksum: 3bca2db0479fd38f8c4c9439139b0c42dcaadcc2fbb7bb8e0e6afaa1383457f1d19aea9e5f961d5b080f1cfc05bfa1fe9e45c97a1d3fd6d421950a73d3108381 + languageName: node + linkType: hard + +"pump@npm:^3.0.0": + version: 3.0.0 + resolution: "pump@npm:3.0.0" + dependencies: + end-of-stream: ^1.1.0 + once: ^1.3.1 + checksum: e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9 + languageName: node + linkType: hard + +"punycode@npm:^1.3.2, punycode@npm:^1.4.1": + version: 1.4.1 + resolution: "punycode@npm:1.4.1" + checksum: fa6e698cb53db45e4628559e557ddaf554103d2a96a1d62892c8f4032cd3bc8871796cae9eabc1bc700e2b6677611521ce5bb1d9a27700086039965d0cf34518 + languageName: node + linkType: hard + +"punycode@npm:^2.1.0, punycode@npm:^2.1.1": + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2 + languageName: node + linkType: hard + +"pupa@npm:^2.1.1": + version: 2.1.1 + resolution: "pupa@npm:2.1.1" + dependencies: + escape-goat: ^2.0.0 + checksum: 49529e50372ffdb0cccf0efa0f3b3cb0a2c77805d0d9cc2725bd2a0f6bb414631e61c93a38561b26be1259550b7bb6c2cb92315aa09c8bf93f3bdcb49f2b2fb7 + languageName: node + linkType: hard + +"pupa@npm:^3.1.0": + version: 3.1.0 + resolution: "pupa@npm:3.1.0" + dependencies: + escape-goat: ^4.0.0 + checksum: 0e4f4ab6bbdce600fa6d23b1833f1af57b2641246ff4cbe10f9d66e4e5479b0de2864a88d5bd629eef59524eda3c6680726acd7f3f873d9ed46b7f095d0bb5f6 + languageName: node + linkType: hard + +"puppeteer-core@npm:^22.0.0": + version: 22.4.1 + resolution: "puppeteer-core@npm:22.4.1" + dependencies: + "@puppeteer/browsers": 2.1.0 + chromium-bidi: 0.5.12 + cross-fetch: 4.0.0 + debug: 4.3.4 + devtools-protocol: 0.0.1249869 + ws: 8.16.0 + checksum: 01c28c4f0f66a4ed6c7fee14871920fd25c60ae3507c1b8aed37968b240021f8d0cdd37cb863cebb88fde792ae9fea453e3b943931ae075c99f8e90303d2625f + languageName: node + linkType: hard + +"qs@npm:6.11.0": + version: 6.11.0 + resolution: "qs@npm:6.11.0" + dependencies: + side-channel: ^1.0.4 + checksum: 6e1f29dd5385f7488ec74ac7b6c92f4d09a90408882d0c208414a34dd33badc1a621019d4c799a3df15ab9b1d0292f97c1dd71dc7c045e69f81a8064e5af7297 + languageName: node + linkType: hard + +"qs@npm:^6.11.2, qs@npm:^6.5.2": + version: 6.11.2 + resolution: "qs@npm:6.11.2" + dependencies: + side-channel: ^1.0.4 + checksum: e812f3c590b2262548647d62f1637b6989cc56656dc960b893fe2098d96e1bd633f36576f4cd7564dfbff9db42e17775884db96d846bebe4f37420d073ecdc0b + languageName: node + linkType: hard + +"queue-microtask@npm:^1.2.2": + version: 1.2.3 + resolution: "queue-microtask@npm:1.2.3" + checksum: b676f8c040cdc5b12723ad2f91414d267605b26419d5c821ff03befa817ddd10e238d22b25d604920340fd73efd8ba795465a0377c4adf45a4a41e4234e42dc4 + languageName: node + linkType: hard + +"queue-tick@npm:^1.0.1": + version: 1.0.1 + resolution: "queue-tick@npm:1.0.1" + checksum: 57c3292814b297f87f792fbeb99ce982813e4e54d7a8bdff65cf53d5c084113913289d4a48ec8bbc964927a74b847554f9f4579df43c969a6c8e0f026457ad01 + languageName: node + linkType: hard + +"queue@npm:6.0.2": + version: 6.0.2 + resolution: "queue@npm:6.0.2" + dependencies: + inherits: ~2.0.3 + checksum: ebc23639248e4fe40a789f713c20548e513e053b3dc4924b6cb0ad741e3f264dcff948225c8737834dd4f9ec286dbc06a1a7c13858ea382d9379f4303bcc0916 + languageName: node + linkType: hard + +"quick-lru@npm:^5.1.1": + version: 5.1.1 + resolution: "quick-lru@npm:5.1.1" + checksum: a516faa25574be7947969883e6068dbe4aa19e8ef8e8e0fd96cddd6d36485e9106d85c0041a27153286b0770b381328f4072aa40d3b18a19f5f7d2b78b94b5ed + languageName: node + linkType: hard + +"randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: ^5.1.0 + checksum: d779499376bd4cbb435ef3ab9a957006c8682f343f14089ed5f27764e4645114196e75b7f6abf1cbd84fd247c0cb0651698444df8c9bf30e62120fbbc52269d6 + languageName: node + linkType: hard + +"range-parser@npm:1.2.0": + version: 1.2.0 + resolution: "range-parser@npm:1.2.0" + checksum: bdf397f43fedc15c559d3be69c01dedf38444ca7a1610f5bf5955e3f3da6057a892f34691e7ebdd8c7e1698ce18ef6c4d4811f70e658dda3ff230ef741f8423a + languageName: node + linkType: hard + +"range-parser@npm:^1.2.1, range-parser@npm:~1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 0a268d4fea508661cf5743dfe3d5f47ce214fd6b7dec1de0da4d669dd4ef3d2144468ebe4179049eff253d9d27e719c88dae55be64f954e80135a0cada804ec9 + languageName: node + linkType: hard + +"raw-body@npm:2.5.1": + version: 2.5.1 + resolution: "raw-body@npm:2.5.1" + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + checksum: 5362adff1575d691bb3f75998803a0ffed8c64eabeaa06e54b4ada25a0cd1b2ae7f4f5ec46565d1bec337e08b5ac90c76eaa0758de6f72a633f025d754dec29e + languageName: node + linkType: hard + +"raw-body@npm:^2.3.3, raw-body@npm:^2.4.1": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + checksum: ba1583c8d8a48e8fbb7a873fdbb2df66ea4ff83775421bfe21ee120140949ab048200668c47d9ae3880012f6e217052690628cf679ddfbd82c9fc9358d574676 + languageName: node + linkType: hard + +"rc@npm:1.2.8, rc@npm:^1.0.1, rc@npm:^1.1.6, rc@npm:^1.2.8": + version: 1.2.8 + resolution: "rc@npm:1.2.8" + dependencies: + deep-extend: ^0.6.0 + ini: ~1.3.0 + minimist: ^1.2.0 + strip-json-comments: ~2.0.1 + bin: + rc: ./cli.js + checksum: 2e26e052f8be2abd64e6d1dabfbd7be03f80ec18ccbc49562d31f617d0015fbdbcf0f9eed30346ea6ab789e0fdfe4337f033f8016efdbee0df5354751842080e + languageName: node + linkType: hard + +"react-dev-utils@npm:^12.0.1": + version: 12.0.1 + resolution: "react-dev-utils@npm:12.0.1" + dependencies: + "@babel/code-frame": ^7.16.0 + address: ^1.1.2 + browserslist: ^4.18.1 + chalk: ^4.1.2 + cross-spawn: ^7.0.3 + detect-port-alt: ^1.1.6 + escape-string-regexp: ^4.0.0 + filesize: ^8.0.6 + find-up: ^5.0.0 + fork-ts-checker-webpack-plugin: ^6.5.0 + global-modules: ^2.0.0 + globby: ^11.0.4 + gzip-size: ^6.0.0 + immer: ^9.0.7 + is-root: ^2.1.0 + loader-utils: ^3.2.0 + open: ^8.4.0 + pkg-up: ^3.1.0 + prompts: ^2.4.2 + react-error-overlay: ^6.0.11 + recursive-readdir: ^2.2.2 + shell-quote: ^1.7.3 + strip-ansi: ^6.0.1 + text-table: ^0.2.0 + checksum: 2c6917e47f03d9595044770b0f883a61c6b660fcaa97b8ba459a1d57c9cca9aa374cd51296b22d461ff5e432105dbe6f04732dab128e52729c79239e1c23ab56 + languageName: node + linkType: hard + +"react-dom@npm:^18.2.0": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" + dependencies: + loose-envify: ^1.1.0 + scheduler: ^0.23.0 + peerDependencies: + react: ^18.2.0 + checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc + languageName: node + linkType: hard + +"react-error-overlay@npm:^6.0.11": + version: 6.0.11 + resolution: "react-error-overlay@npm:6.0.11" + checksum: ce7b44c38fadba9cedd7c095cf39192e632daeccf1d0747292ed524f17dcb056d16bc197ddee5723f9dd888f0b9b19c3b486c430319e30504289b9296f2d2c42 + languageName: node + linkType: hard + +"react-fast-compare@npm:^3.2.0, react-fast-compare@npm:^3.2.2": + version: 3.2.2 + resolution: "react-fast-compare@npm:3.2.2" + checksum: 2071415b4f76a3e6b55c84611c4d24dcb12ffc85811a2840b5a3f1ff2d1a99be1020d9437ee7c6e024c9f4cbb84ceb35e48cf84f28fcb00265ad2dfdd3947704 + languageName: node + linkType: hard + +"react-helmet-async@npm:*": + version: 2.0.3 + resolution: "react-helmet-async@npm:2.0.3" + dependencies: + invariant: ^2.2.4 + react-fast-compare: ^3.2.2 + shallowequal: ^1.1.0 + peerDependencies: + react: ^16.6.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 + checksum: dfb951174c1812b1aaa8099181024ea8fbdc5cb65e5ab56e465753e2dc5a7c7756e9ab86ba382157ff27dc5b33353a2a000f7f088653815e4aa576daec01ec33 + languageName: node + linkType: hard + +"react-helmet-async@npm:^1.3.0": + version: 1.3.0 + resolution: "react-helmet-async@npm:1.3.0" + dependencies: + "@babel/runtime": ^7.12.5 + invariant: ^2.2.4 + prop-types: ^15.7.2 + react-fast-compare: ^3.2.0 + shallowequal: ^1.1.0 + peerDependencies: + react: ^16.6.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 + checksum: 7ca7e47f8af14ea186688b512a87ab912bf6041312b297f92516341b140b3f0f8aedf5a44d226d99e69ed067b0cc106e38aeb9c9b738ffcc63d10721c844db90 + languageName: node + linkType: hard + +"react-is@npm:^16.13.1, react-is@npm:^16.6.0, react-is@npm:^16.7.0": + version: 16.13.1 + resolution: "react-is@npm:16.13.1" + checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f + languageName: node + linkType: hard + +"react-json-view-lite@npm:^1.2.0": + version: 1.2.1 + resolution: "react-json-view-lite@npm:1.2.1" + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + checksum: 9441260033ec07991b0121281d846f9d3e8db9061ea0dc3938f7003630f515d47870a465d90f1f9300ebe406679986657a4062c009c2a2084e2e145e6fa05a47 + languageName: node + linkType: hard + +"react-loadable-ssr-addon-v5-slorber@npm:^1.0.1": + version: 1.0.1 + resolution: "react-loadable-ssr-addon-v5-slorber@npm:1.0.1" + dependencies: + "@babel/runtime": ^7.10.3 + peerDependencies: + react-loadable: "*" + webpack: ">=4.41.1 || 5.x" + checksum: 1cf7ceb488d329a5be15f891dae16727fb7ade08ef57826addd21e2c3d485e2440259ef8be94f4d54e9afb4bcbd2fcc22c3c5bad92160c9c06ae6ba7b5562497 + languageName: node + linkType: hard + +"react-loadable@npm:@docusaurus/react-loadable@6.0.0": + version: 6.0.0 + resolution: "@docusaurus/react-loadable@npm:6.0.0" + dependencies: + "@types/react": "*" + peerDependencies: + react: "*" + checksum: 4c32061b2fc10689d5d8ba11ead71b69e4c8a55fcfeafb551a6747b1a7b496c4f2d8dbb5d023f5cafc2a9aea9d14582bdb324d11e6f9b8c3049d45b74439203f + languageName: node + linkType: hard + +"react-router-config@npm:^5.1.1": + version: 5.1.1 + resolution: "react-router-config@npm:5.1.1" + dependencies: + "@babel/runtime": ^7.1.2 + peerDependencies: + react: ">=15" + react-router: ">=5" + checksum: bde7ee79444454bf7c3737fd9c5c268021012c8cc37bc19116b2e7daa28c4231598c275816c7f32c16f9f974dc707b91de279291a5e39efce2e1b1569355b87a + languageName: node + linkType: hard + +"react-router-dom@npm:^5.3.3, react-router-dom@npm:^5.3.4": + version: 5.3.4 + resolution: "react-router-dom@npm:5.3.4" + dependencies: + "@babel/runtime": ^7.12.13 + history: ^4.9.0 + loose-envify: ^1.3.1 + prop-types: ^15.6.2 + react-router: 5.3.4 + tiny-invariant: ^1.0.2 + tiny-warning: ^1.0.0 + peerDependencies: + react: ">=15" + checksum: b86a6f2f5222f041e38adf4e4b32c7643d6735a1a915ef25855b2db285fd059d72ba8d62e5bcd5d822b8ef9520a80453209e55077f5a90d0f72e908979b8f535 + languageName: node + linkType: hard + +"react-router@npm:5.3.4, react-router@npm:^5.3.3, react-router@npm:^5.3.4": + version: 5.3.4 + resolution: "react-router@npm:5.3.4" + dependencies: + "@babel/runtime": ^7.12.13 + history: ^4.9.0 + hoist-non-react-statics: ^3.1.0 + loose-envify: ^1.3.1 + path-to-regexp: ^1.7.0 + prop-types: ^15.6.2 + react-is: ^16.6.0 + tiny-invariant: ^1.0.2 + tiny-warning: ^1.0.0 + peerDependencies: + react: ">=15" + checksum: 892d4e274a23bf4f39abc2efca54472fb646d3aed4b584020cf49654d2f50d09a2bacebe7c92b4ec7cb8925077376dfcd0664bad6442a73604397cefec9f01f9 + languageName: node + linkType: hard + +"react-spinners@npm:^0.13.8": + version: 0.13.8 + resolution: "react-spinners@npm:0.13.8" + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: cb58f916bbf00c4f7fc33c1a75a8c0f91a98a42af26944340a0e29e4b3a97937a03f0292bc444eb5f5f0bea099344b580f9c04a81524246dadbf0571bdb57e62 + languageName: node + linkType: hard + +"react@npm:^18.2.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + dependencies: + loose-envify: ^1.1.0 + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b + languageName: node + linkType: hard + +"readable-stream@npm:^1.0.26-4": + version: 1.1.14 + resolution: "readable-stream@npm:1.1.14" + dependencies: + core-util-is: ~1.0.0 + inherits: ~2.0.1 + isarray: 0.0.1 + string_decoder: ~0.10.x + checksum: 17dfeae3e909945a4a1abc5613ea92d03269ef54c49288599507fc98ff4615988a1c39a999dcf9aacba70233d9b7040bc11a5f2bfc947e262dedcc0a8b32b5a0 + languageName: node + linkType: hard + +"readable-stream@npm:^2.0.1, readable-stream@npm:^2.2.2": + version: 2.3.8 + resolution: "readable-stream@npm:2.3.8" + dependencies: + core-util-is: ~1.0.0 + inherits: ~2.0.3 + isarray: ~1.0.0 + process-nextick-args: ~2.0.0 + safe-buffer: ~5.1.1 + string_decoder: ~1.1.1 + util-deprecate: ~1.0.1 + checksum: 65645467038704f0c8aaf026a72fbb588a9e2ef7a75cd57a01702ee9db1c4a1e4b03aaad36861a6a0926546a74d174149c8c207527963e0c2d3eee2f37678a42 + languageName: node + linkType: hard + +"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: + inherits: ^2.0.3 + string_decoder: ^1.1.1 + util-deprecate: ^1.0.1 + checksum: bdcbe6c22e846b6af075e32cf8f4751c2576238c5043169a1c221c92ee2878458a816a4ea33f4c67623c0b6827c8a400409bfb3cf0bf3381392d0b1dfb52ac8d + languageName: node + linkType: hard + +"readable-stream@npm:^4.4.2": + version: 4.4.2 + resolution: "readable-stream@npm:4.4.2" + dependencies: + abort-controller: ^3.0.0 + buffer: ^6.0.3 + events: ^3.3.0 + process: ^0.11.10 + string_decoder: ^1.3.0 + checksum: 6f4063763dbdb52658d22d3f49ca976420e1fbe16bbd241f744383715845350b196a2f08b8d6330f8e219153dff34b140aeefd6296da828e1041a7eab1f20d5e + languageName: node + linkType: hard + +"readable-stream@npm:~1.0.26, readable-stream@npm:~1.0.26-4": + version: 1.0.34 + resolution: "readable-stream@npm:1.0.34" + dependencies: + core-util-is: ~1.0.0 + inherits: ~2.0.1 + isarray: 0.0.1 + string_decoder: ~0.10.x + checksum: 85042c537e4f067daa1448a7e257a201070bfec3dd2706abdbd8ebc7f3418eb4d3ed4b8e5af63e2544d69f88ab09c28d5da3c0b77dc76185fddd189a59863b60 + languageName: node + linkType: hard + +"readdirp@npm:~3.6.0": + version: 3.6.0 + resolution: "readdirp@npm:3.6.0" + dependencies: + picomatch: ^2.2.1 + checksum: 1ced032e6e45670b6d7352d71d21ce7edf7b9b928494dcaba6f11fba63180d9da6cd7061ebc34175ffda6ff529f481818c962952004d273178acd70f7059b320 + languageName: node + linkType: hard + +"reading-time@npm:^1.5.0": + version: 1.5.0 + resolution: "reading-time@npm:1.5.0" + checksum: e27bc5a70ba0f4ac337896b18531b914d38f4bee67cbad48029d0c11dd0a7a847b2a6bba895ab7ce2ad3e7ecb86912bdc477d8fa2d48405a3deda964be54d09b + languageName: node + linkType: hard + +"rechoir@npm:^0.6.2": + version: 0.6.2 + resolution: "rechoir@npm:0.6.2" + dependencies: + resolve: ^1.1.6 + checksum: fe76bf9c21875ac16e235defedd7cbd34f333c02a92546142b7911a0f7c7059d2e16f441fe6fb9ae203f459c05a31b2bcf26202896d89e390eda7514d5d2702b + languageName: node + linkType: hard + +"rechoir@npm:^0.8.0": + version: 0.8.0 + resolution: "rechoir@npm:0.8.0" + dependencies: + resolve: ^1.20.0 + checksum: ad3caed8afdefbc33fbc30e6d22b86c35b3d51c2005546f4e79bcc03c074df804b3640ad18945e6bef9ed12caedc035655ec1082f64a5e94c849ff939dc0a788 + languageName: node + linkType: hard + +"recursive-readdir@npm:^2.2.2": + version: 2.2.3 + resolution: "recursive-readdir@npm:2.2.3" + dependencies: + minimatch: ^3.0.5 + checksum: 88ec96e276237290607edc0872b4f9842837b95cfde0cdbb1e00ba9623dfdf3514d44cdd14496ab60a0c2dd180a6ef8a3f1c34599e6cf2273afac9b72a6fb2b5 + languageName: node + linkType: hard + +"reduce-flatten@npm:^2.0.0": + version: 2.0.0 + resolution: "reduce-flatten@npm:2.0.0" + checksum: 64393ef99a16b20692acfd60982d7fdbd7ff8d9f8f185c6023466444c6dd2abb929d67717a83cec7f7f8fb5f46a25d515b3b2bf2238fdbfcdbfd01d2a9e73cb8 + languageName: node + linkType: hard + +"regenerate-unicode-properties@npm:^10.1.0": + version: 10.1.1 + resolution: "regenerate-unicode-properties@npm:10.1.1" + dependencies: + regenerate: ^1.4.2 + checksum: b80958ef40f125275824c2c47d5081dfaefebd80bff26c76761e9236767c748a4a95a69c053fe29d2df881177f2ca85df4a71fe70a82360388b31159ef19adcf + languageName: node + linkType: hard + +"regenerate@npm:^1.4.2": + version: 1.4.2 + resolution: "regenerate@npm:1.4.2" + checksum: 3317a09b2f802da8db09aa276e469b57a6c0dd818347e05b8862959c6193408242f150db5de83c12c3fa99091ad95fb42a6db2c3329bfaa12a0ea4cbbeb30cb0 + languageName: node + linkType: hard + +"regenerator-runtime@npm:^0.14.0": + version: 0.14.0 + resolution: "regenerator-runtime@npm:0.14.0" + checksum: 1c977ad82a82a4412e4f639d65d22be376d3ebdd30da2c003eeafdaaacd03fc00c2320f18120007ee700900979284fc78a9f00da7fb593f6e6eeebc673fba9a3 + languageName: node + linkType: hard + +"regenerator-transform@npm:^0.15.2": + version: 0.15.2 + resolution: "regenerator-transform@npm:0.15.2" + dependencies: + "@babel/runtime": ^7.8.4 + checksum: 20b6f9377d65954980fe044cfdd160de98df415b4bff38fbade67b3337efaf078308c4fed943067cd759827cc8cfeca9cb28ccda1f08333b85d6a2acbd022c27 + languageName: node + linkType: hard + +"regexpu-core@npm:^5.3.1": + version: 5.3.2 + resolution: "regexpu-core@npm:5.3.2" + dependencies: + "@babel/regjsgen": ^0.8.0 + regenerate: ^1.4.2 + regenerate-unicode-properties: ^10.1.0 + regjsparser: ^0.9.1 + unicode-match-property-ecmascript: ^2.0.0 + unicode-match-property-value-ecmascript: ^2.1.0 + checksum: 95bb97088419f5396e07769b7de96f995f58137ad75fac5811fb5fe53737766dfff35d66a0ee66babb1eb55386ef981feaef392f9df6d671f3c124812ba24da2 + languageName: node + linkType: hard + +"registry-auth-token@npm:3.3.2": + version: 3.3.2 + resolution: "registry-auth-token@npm:3.3.2" + dependencies: + rc: ^1.1.6 + safe-buffer: ^5.0.1 + checksum: c9d7ae160a738f1fa825556e3669e6c771d2c0239ce37679f7e8646157a97d0a76464738be075002a1f754ef9bfb913b689f4bbfd5296d28f136fbf98c8c2217 + languageName: node + linkType: hard + +"registry-auth-token@npm:^4.0.0": + version: 4.2.2 + resolution: "registry-auth-token@npm:4.2.2" + dependencies: + rc: 1.2.8 + checksum: c5030198546ecfdcbcb0722cbc3e260c4f5f174d8d07bdfedd4620e79bfdf17a2db735aa230d600bd388fce6edd26c0a9ed2eb7e9b4641ec15213a28a806688b + languageName: node + linkType: hard + +"registry-auth-token@npm:^5.0.1": + version: 5.0.2 + resolution: "registry-auth-token@npm:5.0.2" + dependencies: + "@pnpm/npm-conf": ^2.1.0 + checksum: 0d7683b71ee418993e7872b389024b13645c4295eb7bb850d10728eaf46065db24ea4d47dc6cbb71a60d1aa4bef077b0d8b7363c9ac9d355fdba47bebdfb01dd + languageName: node + linkType: hard + +"registry-url@npm:3.1.0": + version: 3.1.0 + resolution: "registry-url@npm:3.1.0" + dependencies: + rc: ^1.0.1 + checksum: 6d223da41b04e1824f5faa63905c6f2e43b216589d72794111573f017352b790aef42cd1f826463062f89d804abb2027e3d9665d2a9a0426a11eedd04d470af3 + languageName: node + linkType: hard + +"registry-url@npm:^5.0.0": + version: 5.1.0 + resolution: "registry-url@npm:5.1.0" + dependencies: + rc: ^1.2.8 + checksum: bcea86c84a0dbb66467b53187fadebfea79017cddfb4a45cf27530d7275e49082fe9f44301976eb0164c438e395684bcf3dae4819b36ff9d1640d8cc60c73df9 + languageName: node + linkType: hard + +"registry-url@npm:^6.0.0": + version: 6.0.1 + resolution: "registry-url@npm:6.0.1" + dependencies: + rc: 1.2.8 + checksum: 33712aa1b489aab7aba2191c1cdadfdd71f5bf166d4792d81744a6be332c160bd7d9273af8269d8a01284b9562f14a5b31b7abcf7ad9306c44887ecff51c89ab + languageName: node + linkType: hard + +"regjsparser@npm:^0.9.1": + version: 0.9.1 + resolution: "regjsparser@npm:0.9.1" + dependencies: + jsesc: ~0.5.0 + bin: + regjsparser: bin/parser + checksum: 5e1b76afe8f1d03c3beaf9e0d935dd467589c3625f6d65fb8ffa14f224d783a0fed4bf49c2c1b8211043ef92b6117313419edf055a098ed8342e340586741afc + languageName: node + linkType: hard + +"rehype-katex@npm:^7.0.0": + version: 7.0.0 + resolution: "rehype-katex@npm:7.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/katex": ^0.16.0 + hast-util-from-html-isomorphic: ^2.0.0 + hast-util-to-text: ^4.0.0 + katex: ^0.16.0 + unist-util-visit-parents: ^6.0.0 + vfile: ^6.0.0 + checksum: 3184cf7635e63039a5d455e27718cbc99998cc7bfcc15422badf5da892887f4200f3ee54a6617aa231aa15d46cb678716c112b6b7f9cef11a8653e5d518ad6f0 + languageName: node + linkType: hard + +"rehype-raw@npm:^7.0.0": + version: 7.0.0 + resolution: "rehype-raw@npm:7.0.0" + dependencies: + "@types/hast": ^3.0.0 + hast-util-raw: ^9.0.0 + vfile: ^6.0.0 + checksum: f9e28dcbf4c6c7d91a97c10a840310f18ef3268aa45abb3e0428b6b191ff3c4fa8f753b910d768588a2dac5c7da7e557b4ddc3f1b6cd252e8d20cb62d60c65ed + languageName: node + linkType: hard + +"relateurl@npm:^0.2.7": + version: 0.2.7 + resolution: "relateurl@npm:0.2.7" + checksum: 5891e792eae1dfc3da91c6fda76d6c3de0333a60aa5ad848982ebb6dccaa06e86385fb1235a1582c680a3d445d31be01c6bfc0804ebbcab5aaf53fa856fde6b6 + languageName: node + linkType: hard + +"remark-directive@npm:^3.0.0": + version: 3.0.0 + resolution: "remark-directive@npm:3.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-directive: ^3.0.0 + micromark-extension-directive: ^3.0.0 + unified: ^11.0.0 + checksum: 744d12bbe924bd0492a2481cbaf9250aa6622c0d2cc090bb7bc39975e355c8a46ae13cc4793204ada39f0af64c953f6b730a55420a50375e0f74a5dd5d201089 + languageName: node + linkType: hard + +"remark-emoji@npm:^2.2.0": + version: 2.2.0 + resolution: "remark-emoji@npm:2.2.0" + dependencies: + emoticon: ^3.2.0 + node-emoji: ^1.10.0 + unist-util-visit: ^2.0.3 + checksum: 638d4be72eb4110a447f389d4b8c454921f188c0acabf1b6579f3ddaa301ee91010173d6eebd975ea622ae3de7ed4531c0315a4ffd4f9653d80c599ef9ec21a8 + languageName: node + linkType: hard + +"remark-emoji@npm:^4.0.0": + version: 4.0.1 + resolution: "remark-emoji@npm:4.0.1" + dependencies: + "@types/mdast": ^4.0.2 + emoticon: ^4.0.1 + mdast-util-find-and-replace: ^3.0.1 + node-emoji: ^2.1.0 + unified: ^11.0.4 + checksum: 2c02d8c0b694535a9f0c4fe39180cb89a8fbd07eb873c94842c34dfde566b8a6703df9d28fe175a8c28584f96252121de722862baa756f2d875f2f1a4352c1f4 + languageName: node + linkType: hard + +"remark-footnotes@npm:2.0.0": + version: 2.0.0 + resolution: "remark-footnotes@npm:2.0.0" + checksum: f2f87ffd6fe25892373c7164d6584a7cb03ab0ea4f186af493a73df519e24b72998a556e7f16cb996f18426cdb80556b95ff252769e252cf3ccba0fd2ca20621 + languageName: node + linkType: hard + +"remark-frontmatter@npm:^5.0.0": + version: 5.0.0 + resolution: "remark-frontmatter@npm:5.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-frontmatter: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + unified: ^11.0.0 + checksum: b36e11d528d1d0172489c74ce7961bb6073f7272e71ea1349f765fc79c4246a758aef949174d371a088c48e458af776fcfbb3b043c49cd1120ca8239aeafe16a + languageName: node + linkType: hard + +"remark-gfm@npm:^4.0.0": + version: 4.0.0 + resolution: "remark-gfm@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-gfm: ^3.0.0 + micromark-extension-gfm: ^3.0.0 + remark-parse: ^11.0.0 + remark-stringify: ^11.0.0 + unified: ^11.0.0 + checksum: 84bea84e388061fbbb697b4b666089f5c328aa04d19dc544c229b607446bc10902e46b67b9594415a1017bbbd7c811c1f0c30d36682c6d1a6718b66a1558261b + languageName: node + linkType: hard + +"remark-math@npm:^6.0.0": + version: 6.0.0 + resolution: "remark-math@npm:6.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-math: ^3.0.0 + micromark-extension-math: ^3.0.0 + unified: ^11.0.0 + checksum: fef489acb6cae6e40af05012367dc22a846ce16301e8a96006c6d78935887bdb3e6c5018b6514884ecee57f9c7a51f97a10862526ab0a0f5f7b7d339fe0eb20f + languageName: node + linkType: hard + +"remark-mdx@npm:1.6.22": + version: 1.6.22 + resolution: "remark-mdx@npm:1.6.22" + dependencies: + "@babel/core": 7.12.9 + "@babel/helper-plugin-utils": 7.10.4 + "@babel/plugin-proposal-object-rest-spread": 7.12.1 + "@babel/plugin-syntax-jsx": 7.12.1 + "@mdx-js/util": 1.6.22 + is-alphabetical: 1.0.4 + remark-parse: 8.0.3 + unified: 9.2.0 + checksum: 45e62f8a821c37261f94448d54f295de1c5c393f762ff96cd4d4b730715037fafeb6c89ef94adf6a10a09edfa72104afe1431b93b5ae5e40ce2a7677e133c3d9 + languageName: node + linkType: hard + +"remark-mdx@npm:^3.0.0": + version: 3.0.0 + resolution: "remark-mdx@npm:3.0.0" + dependencies: + mdast-util-mdx: ^3.0.0 + micromark-extension-mdxjs: ^3.0.0 + checksum: 8b9b3e5297e5cb4c312553f42c3720280ada96ae60ede880606924a0aad2e773106aba1ef45a0c179c218f8da6f58dac3c789a9c4f791649ca7a183706cde5b8 + languageName: node + linkType: hard + +"remark-parse@npm:8.0.3": + version: 8.0.3 + resolution: "remark-parse@npm:8.0.3" + dependencies: + ccount: ^1.0.0 + collapse-white-space: ^1.0.2 + is-alphabetical: ^1.0.0 + is-decimal: ^1.0.0 + is-whitespace-character: ^1.0.0 + is-word-character: ^1.0.0 + markdown-escapes: ^1.0.0 + parse-entities: ^2.0.0 + repeat-string: ^1.5.4 + state-toggle: ^1.0.0 + trim: 0.0.1 + trim-trailing-lines: ^1.0.0 + unherit: ^1.0.4 + unist-util-remove-position: ^2.0.0 + vfile-location: ^3.0.0 + xtend: ^4.0.1 + checksum: 2dfea250e7606ddfc9e223b9f41e0b115c5c701be4bd35181beaadd46ee59816bc00aadc6085a420f8df00b991ada73b590ea7fd34ace14557de4a0a41805be5 + languageName: node + linkType: hard + +"remark-parse@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-parse@npm:11.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-from-markdown: ^2.0.0 + micromark-util-types: ^2.0.0 + unified: ^11.0.0 + checksum: d83d245290fa84bb04fb3e78111f09c74f7417e7c012a64dd8dc04fccc3699036d828fbd8eeec8944f774b6c30cc1d925c98f8c46495ebcee7c595496342ab7f + languageName: node + linkType: hard + +"remark-rehype@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-rehype@npm:11.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + mdast-util-to-hast: ^13.0.0 + unified: ^11.0.0 + vfile: ^6.0.0 + checksum: 0ff0fd948759cbde9d507ca1581028d0b89da0b5f610b35a6cb0a511f8d11621449b6eca573b11ddaea77afd37edd4755f3f1eb086ad49a6f7b970b4a4634e13 + languageName: node + linkType: hard + +"remark-squeeze-paragraphs@npm:4.0.0": + version: 4.0.0 + resolution: "remark-squeeze-paragraphs@npm:4.0.0" + dependencies: + mdast-squeeze-paragraphs: ^4.0.0 + checksum: 2071eb74d0ecfefb152c4932690a9fd950c3f9f798a676f1378a16db051da68fb20bf288688cc153ba5019dded35408ff45a31dfe9686eaa7a9f1df9edbb6c81 + languageName: node + linkType: hard + +"remark-stringify@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-stringify@npm:11.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-to-markdown: ^2.0.0 + unified: ^11.0.0 + checksum: 59e07460eb629d6c3b3c0f438b0b236e7e6858fd5ab770303078f5a556ec00354d9c7fb9ef6d5f745a4617ac7da1ab618b170fbb4dac120e183fecd9cc86bce6 + languageName: node + linkType: hard + +"renderkid@npm:^3.0.0": + version: 3.0.0 + resolution: "renderkid@npm:3.0.0" + dependencies: + css-select: ^4.1.3 + dom-converter: ^0.2.0 + htmlparser2: ^6.1.0 + lodash: ^4.17.21 + strip-ansi: ^6.0.1 + checksum: 77162b62d6f33ab81f337c39efce0439ff0d1f6d441e29c35183151f83041c7850774fb904da163d6c844264d440d10557714e6daa0b19e4561a5cd4ef305d41 + languageName: node + linkType: hard + +"repeat-string@npm:^1.5.4, repeat-string@npm:^1.6.1": + version: 1.6.1 + resolution: "repeat-string@npm:1.6.1" + checksum: 1b809fc6db97decdc68f5b12c4d1a671c8e3f65ec4a40c238bc5200e44e85bcc52a54f78268ab9c29fcf5fe4f1343e805420056d1f30fa9a9ee4c2d93e3cc6c0 + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: fb47e70bf0001fdeabdc0429d431863e9475e7e43ea5f94ad86503d918423c1543361cc5166d713eaa7029dd7a3d34775af04764bebff99ef413111a5af18c80 + languageName: node + linkType: hard + +"require-from-string@npm:^2.0.2": + version: 2.0.2 + resolution: "require-from-string@npm:2.0.2" + checksum: a03ef6895445f33a4015300c426699bc66b2b044ba7b670aa238610381b56d3f07c686251740d575e22f4c87531ba662d06937508f0f3c0f1ddc04db3130560b + languageName: node + linkType: hard + +"require-like@npm:>= 0.1.1": + version: 0.1.2 + resolution: "require-like@npm:0.1.2" + checksum: edb8331f05fd807381a75b76f6cca9f0ce8acaa2e910b7e116541799aa970bfbc64fde5fd6adb3a6917dba346f8386ebbddb81614c24e8dad1b4290c7af9535e + languageName: node + linkType: hard + +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: eee0e303adffb69be55d1a214e415cf42b7441ae858c76dfc5353148644f6fd6e698926fc4643f510d5c126d12a705e7c8ed7e38061113bdf37547ab356797ff + languageName: node + linkType: hard + +"resolve-alpn@npm:^1.2.0": + version: 1.2.1 + resolution: "resolve-alpn@npm:1.2.1" + checksum: f558071fcb2c60b04054c99aebd572a2af97ef64128d59bef7ab73bd50d896a222a056de40ffc545b633d99b304c259ea9d0c06830d5c867c34f0bfa60b8eae0 + languageName: node + linkType: hard + +"resolve-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-cwd@npm:3.0.0" + dependencies: + resolve-from: ^5.0.0 + checksum: 546e0816012d65778e580ad62b29e975a642989108d9a3c5beabfb2304192fa3c9f9146fbdfe213563c6ff51975ae41bac1d3c6e047dd9572c94863a057b4d81 + languageName: node + linkType: hard + +"resolve-from@npm:^4.0.0": + version: 4.0.0 + resolution: "resolve-from@npm:4.0.0" + checksum: f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f + languageName: node + linkType: hard + +"resolve-from@npm:^5.0.0": + version: 5.0.0 + resolution: "resolve-from@npm:5.0.0" + checksum: 4ceeb9113e1b1372d0cd969f3468fa042daa1dd9527b1b6bb88acb6ab55d8b9cd65dbf18819f9f9ddf0db804990901dcdaade80a215e7b2c23daae38e64f5bdf + languageName: node + linkType: hard + +"resolve-path@npm:^1.4.0": + version: 1.4.0 + resolution: "resolve-path@npm:1.4.0" + dependencies: + http-errors: ~1.6.2 + path-is-absolute: 1.0.1 + checksum: 1a39f569ee54dd5f8ee8576ef8671c9724bea65d9f9982fbb5352af9fb4e500e1e459c1bfb1ae3ebfd8d43a709c3a01dfa4f46cf5b831e45e2caed4f1a208300 + languageName: node + linkType: hard + +"resolve-pathname@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-pathname@npm:3.0.0" + checksum: 6147241ba42c423dbe83cb067a2b4af4f60908c3af57e1ea567729cc71416c089737fe2a73e9e79e7a60f00f66c91e4b45ad0d37cd4be2d43fec44963ef14368 + languageName: node + linkType: hard + +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 1012afc566b3fdb190a6309cc37ef3b2dcc35dff5fa6683a9d00cd25c3247edfbc4691b91078c97adc82a29b77a2660c30d791d65dab4fc78bfc473f60289977 + languageName: node + linkType: hard + +"resolve@npm:1.17.0": + version: 1.17.0 + resolution: "resolve@npm:1.17.0" + dependencies: + path-parse: ^1.0.6 + checksum: 9ceaf83b3429f2d7ff5d0281b8d8f18a1f05b6ca86efea7633e76b8f76547f33800799dfdd24434942dec4fbd9e651ed3aef577d9a6b5ec87ad89c1060e24759 + languageName: node + linkType: hard + +"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: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: f8a26958aa572c9b064562750b52131a37c29d072478ea32e129063e2da7f83e31f7f11e7087a18225a8561cfe8d2f0df9dbea7c9d331a897571c0a2527dbb4c + languageName: node + linkType: hard + +"resolve@patch:resolve@1.17.0#~builtin": + version: 1.17.0 + resolution: "resolve@patch:resolve@npm%3A1.17.0#~builtin::version=1.17.0&hash=c3c19d" + dependencies: + path-parse: ^1.0.6 + checksum: 6fd799f282ddf078c4bc20ce863e3af01fa8cb218f0658d9162c57161a2dbafe092b13015b9a4c58d0e1e801cf7aa7a4f13115fea9db98c3f9a0c43e429bad6f + languageName: node + linkType: hard + +"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: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 5479b7d431cacd5185f8db64bfcb7286ae5e31eb299f4c4f404ad8aa6098b77599563ac4257cb2c37a42f59dfc06a1bec2bcf283bb448f319e37f0feb9a09847 + languageName: node + linkType: hard + +"responselike@npm:^1.0.2": + version: 1.0.2 + resolution: "responselike@npm:1.0.2" + dependencies: + lowercase-keys: ^1.0.0 + checksum: 2e9e70f1dcca3da621a80ce71f2f9a9cad12c047145c6ece20df22f0743f051cf7c73505e109814915f23f9e34fb0d358e22827723ee3d56b623533cab8eafcd + languageName: node + linkType: hard + +"responselike@npm:^3.0.0": + version: 3.0.0 + resolution: "responselike@npm:3.0.0" + dependencies: + lowercase-keys: ^3.0.0 + checksum: e0cc9be30df4f415d6d83cdede3c5c887cd4a73e7cc1708bcaab1d50a28d15acb68460ac5b02bcc55a42f3d493729c8856427dcf6e57e6e128ad05cba4cfb95e + languageName: node + linkType: hard + +"restore-cursor@npm:^3.1.0": + version: 3.1.0 + resolution: "restore-cursor@npm:3.1.0" + dependencies: + onetime: ^5.1.0 + signal-exit: ^3.0.2 + checksum: f877dd8741796b909f2a82454ec111afb84eb45890eb49ac947d87991379406b3b83ff9673a46012fca0d7844bb989f45cc5b788254cf1a39b6b5a9659de0630 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 623bd7d2e5119467ba66202d733ec3c2e2e26568074923bc0585b6b99db14f357e79bdedb63cab56cec47491c4a0da7e6021a7465ca6dc4f481d3898fdd3158c + languageName: node + linkType: hard + +"retry@npm:^0.13.1": + version: 0.13.1 + resolution: "retry@npm:0.13.1" + checksum: 47c4d5be674f7c13eee4cfe927345023972197dbbdfba5d3af7e461d13b44de1bfd663bfc80d2f601f8ef3fc8164c16dd99655a221921954a65d044a2fc1233b + languageName: node + linkType: hard + +"reusify@npm:^1.0.4": + version: 1.0.4 + resolution: "reusify@npm:1.0.4" + checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc + languageName: node + linkType: hard + +"rimraf@npm:^3.0.2": + version: 3.0.2 + resolution: "rimraf@npm:3.0.2" + dependencies: + glob: ^7.1.3 + bin: + rimraf: bin.js + checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 + languageName: node + linkType: hard + +"rimraf@npm:^5.0.5": + version: 5.0.5 + resolution: "rimraf@npm:5.0.5" + dependencies: + glob: ^10.3.7 + bin: + rimraf: dist/esm/bin.mjs + checksum: d66eef829b2e23b16445f34e73d75c7b7cf4cbc8834b04720def1c8f298eb0753c3d76df77325fad79d0a2c60470525d95f89c2475283ad985fd7441c32732d1 + languageName: node + linkType: hard + +"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1": + version: 2.0.2 + resolution: "ripemd160@npm:2.0.2" + dependencies: + hash-base: ^3.0.0 + inherits: ^2.0.1 + checksum: 006accc40578ee2beae382757c4ce2908a826b27e2b079efdcd2959ee544ddf210b7b5d7d5e80467807604244e7388427330f5c6d4cd61e6edaddc5773ccc393 + languageName: node + linkType: hard + +"rlp@npm:^2.2.3": + version: 2.2.7 + resolution: "rlp@npm:2.2.7" + dependencies: + bn.js: ^5.2.0 + bin: + rlp: bin/rlp + checksum: 3db4dfe5c793f40ac7e0be689a1f75d05e6f2ca0c66189aeb62adab8c436b857ab4420a419251ee60370d41d957a55698fc5e23ab1e1b41715f33217bc4bb558 + languageName: node + linkType: hard + +"rollup@npm:^4.4.0": + version: 4.9.4 + resolution: "rollup@npm:4.9.4" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.9.4 + "@rollup/rollup-android-arm64": 4.9.4 + "@rollup/rollup-darwin-arm64": 4.9.4 + "@rollup/rollup-darwin-x64": 4.9.4 + "@rollup/rollup-linux-arm-gnueabihf": 4.9.4 + "@rollup/rollup-linux-arm64-gnu": 4.9.4 + "@rollup/rollup-linux-arm64-musl": 4.9.4 + "@rollup/rollup-linux-riscv64-gnu": 4.9.4 + "@rollup/rollup-linux-x64-gnu": 4.9.4 + "@rollup/rollup-linux-x64-musl": 4.9.4 + "@rollup/rollup-win32-arm64-msvc": 4.9.4 + "@rollup/rollup-win32-ia32-msvc": 4.9.4 + "@rollup/rollup-win32-x64-msvc": 4.9.4 + "@types/estree": 1.0.5 + fsevents: ~2.3.2 + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 134b1fd8886a1dc86b2cadada979174e736a39aec12d069261fe8b799ad0c4aa3213188ea49adeee155669315016617260e43eea754436c50121aa359899da4d + languageName: node + linkType: hard + +"rtl-detect@npm:^1.0.4": + version: 1.1.2 + resolution: "rtl-detect@npm:1.1.2" + checksum: 4a43a1e5df0617eb86d5485640b318787d12b86acf53d840a3b2ff701ee941e95479d4e9ae97e907569ec763d1c47218cb87639bc87bcdad60a85747e5270cf0 + languageName: node + linkType: hard + +"rtlcss@npm:^4.1.0": + version: 4.1.1 + resolution: "rtlcss@npm:4.1.1" + dependencies: + escalade: ^3.1.1 + picocolors: ^1.0.0 + postcss: ^8.4.21 + strip-json-comments: ^3.1.1 + bin: + rtlcss: bin/rtlcss.js + checksum: dcf37d76265b5c84d610488afa68a2506d008f95feac968b35ccae9aa49e7019ae0336a80363303f8f8bbf60df3ecdeb60413548b049114a24748319b68aefde + languageName: node + linkType: hard + +"run-applescript@npm:^7.0.0": + version: 7.0.0 + resolution: "run-applescript@npm:7.0.0" + checksum: b02462454d8b182ad4117e5d4626e9e6782eb2072925c9fac582170b0627ae3c1ea92ee9b2df7daf84b5e9ffe14eb1cf5fb70bc44b15c8a0bfcdb47987e2410c + languageName: node + linkType: hard + +"run-parallel@npm:^1.1.9": + version: 1.2.0 + resolution: "run-parallel@npm:1.2.0" + dependencies: + queue-microtask: ^1.2.2 + checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d + languageName: node + linkType: hard + +"rxjs@npm:^7.5.4": + version: 7.8.1 + resolution: "rxjs@npm:7.8.1" + dependencies: + tslib: ^2.1.0 + checksum: de4b53db1063e618ec2eca0f7965d9137cabe98cf6be9272efe6c86b47c17b987383df8574861bcced18ebd590764125a901d5506082be84a8b8e364bf05f119 + languageName: node + linkType: hard + +"safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c + languageName: node + linkType: hard + +"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 + languageName: node + linkType: hard + +"sax@npm:^1.2.4": + version: 1.3.0 + resolution: "sax@npm:1.3.0" + checksum: 238ab3a9ba8c8f8aaf1c5ea9120386391f6ee0af52f1a6a40bbb6df78241dd05d782f2359d614ac6aae08c4c4125208b456548a6cf68625aa4fe178486e63ecd + languageName: node + linkType: hard + +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" + dependencies: + loose-envify: ^1.1.0 + checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a + languageName: node + linkType: hard + +"schema-utils@npm:2.7.0": + version: 2.7.0 + resolution: "schema-utils@npm:2.7.0" + dependencies: + "@types/json-schema": ^7.0.4 + ajv: ^6.12.2 + ajv-keywords: ^3.4.1 + checksum: 8889325b0ee1ae6a8f5d6aaa855c71e136ebbb7fd731b01a9d3ec8225dcb245f644c47c50104db4c741983b528cdff8558570021257d4d397ec6aaecd9172a8e + languageName: node + linkType: hard + +"schema-utils@npm:^2.6.5": + version: 2.7.1 + resolution: "schema-utils@npm:2.7.1" + dependencies: + "@types/json-schema": ^7.0.5 + ajv: ^6.12.4 + ajv-keywords: ^3.5.2 + checksum: 32c62fc9e28edd101e1bd83453a4216eb9bd875cc4d3775e4452b541908fa8f61a7bbac8ffde57484f01d7096279d3ba0337078e85a918ecbeb72872fb09fb2b + languageName: node + linkType: hard + +"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1, schema-utils@npm:^3.2.0": + version: 3.3.0 + resolution: "schema-utils@npm:3.3.0" + dependencies: + "@types/json-schema": ^7.0.8 + ajv: ^6.12.5 + ajv-keywords: ^3.5.2 + checksum: ea56971926fac2487f0757da939a871388891bc87c6a82220d125d587b388f1704788f3706e7f63a7b70e49fc2db974c41343528caea60444afd5ce0fe4b85c0 + languageName: node + linkType: hard + +"schema-utils@npm:^4.0.0, schema-utils@npm:^4.0.1, schema-utils@npm:^4.2.0": + version: 4.2.0 + resolution: "schema-utils@npm:4.2.0" + dependencies: + "@types/json-schema": ^7.0.9 + ajv: ^8.9.0 + ajv-formats: ^2.1.1 + ajv-keywords: ^5.1.0 + checksum: 26a0463d47683258106e6652e9aeb0823bf0b85843039e068b57da1892f7ae6b6b1094d48e9ed5ba5cbe9f7166469d880858b9d91abe8bd249421eb813850cde + languageName: node + linkType: hard + +"scrypt-js@npm:^3.0.0": + version: 3.0.1 + resolution: "scrypt-js@npm:3.0.1" + checksum: b7c7d1a68d6ca946f2fbb0778e0c4ec63c65501b54023b2af7d7e9f48fdb6c6580d6f7675cd53bda5944c5ebc057560d5a6365079752546865defb3b79dea454 + languageName: node + linkType: hard + +"secp256k1@npm:^4.0.1": + version: 4.0.3 + resolution: "secp256k1@npm:4.0.3" + dependencies: + elliptic: ^6.5.4 + node-addon-api: ^2.0.0 + node-gyp: latest + node-gyp-build: ^4.2.0 + checksum: 21e219adc0024fbd75021001358780a3cc6ac21273c3fcaef46943af73969729709b03f1df7c012a0baab0830fb9a06ccc6b42f8d50050c665cb98078eab477b + languageName: node + linkType: hard + +"section-matter@npm:^1.0.0": + version: 1.0.0 + resolution: "section-matter@npm:1.0.0" + dependencies: + extend-shallow: ^2.0.1 + kind-of: ^6.0.0 + checksum: 3cc4131705493b2955729b075dcf562359bba66183debb0332752dc9cad35616f6da7a23e42b6cab45cd2e4bb5cda113e9e84c8f05aee77adb6b0289a0229101 + languageName: node + linkType: hard + +"select-hose@npm:^2.0.0": + version: 2.0.0 + resolution: "select-hose@npm:2.0.0" + checksum: d7e5fcc695a4804209d232a1b18624a5134be334d4e1114b0721f7a5e72bd73da483dcf41528c1af4f4f4892ad7cfd6a1e55c8ffb83f9c9fe723b738db609dbb + languageName: node + linkType: hard + +"selfsigned@npm:^2.1.1, selfsigned@npm:^2.4.1": + version: 2.4.1 + resolution: "selfsigned@npm:2.4.1" + dependencies: + "@types/node-forge": ^1.3.0 + node-forge: ^1 + checksum: 38b91c56f1d7949c0b77f9bbe4545b19518475cae15e7d7f0043f87b1626710b011ce89879a88969651f650a19d213bb15b7d5b4c2877df9eeeff7ba8f8b9bfa + languageName: node + linkType: hard + +"semver-diff@npm:^3.1.1": + version: 3.1.1 + resolution: "semver-diff@npm:3.1.1" + dependencies: + semver: ^6.3.0 + checksum: 8bbe5a5d7add2d5e51b72314a9215cd294d71f41cdc2bf6bd59ee76411f3610b576172896f1d191d0d7294cb9f2f847438d2ee158adacc0c224dca79052812fe + languageName: node + linkType: hard + +"semver-diff@npm:^4.0.0": + version: 4.0.0 + resolution: "semver-diff@npm:4.0.0" + dependencies: + semver: ^7.3.5 + checksum: 4a958d6f76c7e7858268e1e2cf936712542441c9e003e561b574167279eee0a9bd55cc7eae1bfb31d3e7ad06a9fc370e7dd412fcfefec8c0daf1ce5aea623559 + languageName: node + linkType: hard + +"semver@npm: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" + bin: + semver: bin/semver + checksum: fb4ab5e0dd1c22ce0c937ea390b4a822147a9c53dbd2a9a0132f12fe382902beef4fbf12cf51bb955248d8d15874ce8cd89532569756384f994309825f10b686 + languageName: node + linkType: hard + +"semver@npm:^6.0.0, semver@npm:^6.2.0, semver@npm:^6.3.0, semver@npm:^6.3.1": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 + languageName: node + linkType: hard + +"semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": + version: 7.5.4 + resolution: "semver@npm:7.5.4" + dependencies: + lru-cache: ^6.0.0 + bin: + semver: bin/semver.js + checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 + languageName: node + linkType: hard + +"semver@npm:~2.3.1": + version: 2.3.2 + resolution: "semver@npm:2.3.2" + bin: + semver: ./bin/semver + checksum: e0649fb18a1da909df7b5a6f586314a7f6e052385fc1e6eafa7084dd77c0787e755ab35ca491f9eec986fe1d0d6d36eae85a21eb7e2ed32ae5906796acb92c56 + languageName: node + linkType: hard + +"send@npm:0.18.0": + version: 0.18.0 + resolution: "send@npm:0.18.0" + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + etag: ~1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: ~1.2.1 + statuses: 2.0.1 + checksum: 74fc07ebb58566b87b078ec63e5a3e41ecd987e4272ba67b7467e86c6ad51bc6b0b0154133b6d8b08a2ddda360464f71382f7ef864700f34844a76c8027817a8 + languageName: node + linkType: hard + +"serialize-javascript@npm:6.0.0": + version: 6.0.0 + resolution: "serialize-javascript@npm:6.0.0" + dependencies: + randombytes: ^2.1.0 + checksum: 56f90b562a1bdc92e55afb3e657c6397c01a902c588c0fe3d4c490efdcc97dcd2a3074ba12df9e94630f33a5ce5b76a74784a7041294628a6f4306e0ec84bf93 + languageName: node + linkType: hard + +"serialize-javascript@npm:^6.0.0, serialize-javascript@npm:^6.0.1": + version: 6.0.1 + resolution: "serialize-javascript@npm:6.0.1" + dependencies: + randombytes: ^2.1.0 + checksum: 3c4f4cb61d0893b988415bdb67243637333f3f574e9e9cc9a006a2ced0b390b0b3b44aef8d51c951272a9002ec50885eefdc0298891bc27eb2fe7510ea87dc4f + languageName: node + linkType: hard + +"serialize-javascript@npm:^6.0.2": + version: 6.0.2 + resolution: "serialize-javascript@npm:6.0.2" + dependencies: + randombytes: ^2.1.0 + checksum: c4839c6206c1d143c0f80763997a361310305751171dd95e4b57efee69b8f6edd8960a0b7fbfc45042aadff98b206d55428aee0dc276efe54f100899c7fa8ab7 + languageName: node + linkType: hard + +"serve-handler@npm:6.1.5, serve-handler@npm:^6.1.3, serve-handler@npm:^6.1.5": + version: 6.1.5 + resolution: "serve-handler@npm:6.1.5" + dependencies: + bytes: 3.0.0 + content-disposition: 0.5.2 + fast-url-parser: 1.1.3 + mime-types: 2.1.18 + minimatch: 3.1.2 + path-is-inside: 1.0.2 + path-to-regexp: 2.2.1 + range-parser: 1.2.0 + checksum: 7a98ca9cbf8692583b6cde4deb3941cff900fa38bf16adbfccccd8430209bab781e21d9a1f61c9c03e226f9f67689893bbce25941368f3ddaf985fc3858b49dc + languageName: node + linkType: hard + +"serve-index@npm:^1.9.1": + version: 1.9.1 + resolution: "serve-index@npm:1.9.1" + dependencies: + accepts: ~1.3.4 + batch: 0.6.1 + debug: 2.6.9 + escape-html: ~1.0.3 + http-errors: ~1.6.2 + mime-types: ~2.1.17 + parseurl: ~1.3.2 + checksum: e2647ce13379485b98a53ba2ea3fbad4d44b57540d00663b02b976e426e6194d62ac465c0d862cb7057f65e0de8ab8a684aa095427a4b8612412eca0d300d22f + languageName: node + linkType: hard + +"serve-static@npm:1.15.0": + version: 1.15.0 + resolution: "serve-static@npm:1.15.0" + dependencies: + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + parseurl: ~1.3.3 + send: 0.18.0 + checksum: af57fc13be40d90a12562e98c0b7855cf6e8bd4c107fe9a45c212bf023058d54a1871b1c89511c3958f70626fff47faeb795f5d83f8cf88514dbaeb2b724464d + languageName: node + linkType: hard + +"serve@npm:^14.2.1": + version: 14.2.1 + resolution: "serve@npm:14.2.1" + dependencies: + "@zeit/schemas": 2.29.0 + ajv: 8.11.0 + arg: 5.0.2 + boxen: 7.0.0 + chalk: 5.0.1 + chalk-template: 0.4.0 + clipboardy: 3.0.0 + compression: 1.7.4 + is-port-reachable: 4.0.0 + serve-handler: 6.1.5 + update-check: 1.5.4 + bin: + serve: build/main.js + checksum: c39a517b5d795a0a5c2f9fb9ff088b7e4962c579e34ace5b85dd62f93e0eacbc8a90359792c153c444a83258ffda392113dff7bfd10d41ced574a2d1886c2994 + languageName: node + linkType: hard + +"set-function-length@npm:^1.1.1": + version: 1.1.1 + resolution: "set-function-length@npm:1.1.1" + dependencies: + define-data-property: ^1.1.1 + get-intrinsic: ^1.2.1 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + checksum: c131d7569cd7e110cafdfbfbb0557249b538477624dfac4fc18c376d879672fa52563b74029ca01f8f4583a8acb35bb1e873d573a24edb80d978a7ee607c6e06 + languageName: node + linkType: hard + +"setimmediate@npm:^1.0.5": + version: 1.0.5 + resolution: "setimmediate@npm:1.0.5" + checksum: c9a6f2c5b51a2dabdc0247db9c46460152ffc62ee139f3157440bd48e7c59425093f42719ac1d7931f054f153e2d26cf37dfeb8da17a794a58198a2705e527fd + languageName: node + linkType: hard + +"setprototypeof@npm:1.1.0": + version: 1.1.0 + resolution: "setprototypeof@npm:1.1.0" + checksum: 27cb44304d6c9e1a23bc6c706af4acaae1a7aa1054d4ec13c05f01a99fd4887109a83a8042b67ad90dbfcd100d43efc171ee036eb080667172079213242ca36e + languageName: node + linkType: hard + +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: be18cbbf70e7d8097c97f713a2e76edf84e87299b40d085c6bf8b65314e994cc15e2e317727342fa6996e38e1f52c59720b53fe621e2eb593a6847bf0356db89 + languageName: node + linkType: hard + +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.8": + version: 2.4.11 + resolution: "sha.js@npm:2.4.11" + dependencies: + inherits: ^2.0.1 + safe-buffer: ^5.0.1 + bin: + sha.js: ./bin.js + checksum: ebd3f59d4b799000699097dadb831c8e3da3eb579144fd7eb7a19484cbcbb7aca3c68ba2bb362242eb09e33217de3b4ea56e4678184c334323eca24a58e3ad07 + languageName: node + linkType: hard + +"shallow-clone@npm:^3.0.0": + version: 3.0.1 + resolution: "shallow-clone@npm:3.0.1" + dependencies: + kind-of: ^6.0.2 + checksum: 39b3dd9630a774aba288a680e7d2901f5c0eae7b8387fc5c8ea559918b29b3da144b7bdb990d7ccd9e11be05508ac9e459ce51d01fd65e583282f6ffafcba2e7 + languageName: node + linkType: hard + +"shallowequal@npm:^1.1.0": + version: 1.1.0 + resolution: "shallowequal@npm:1.1.0" + checksum: f4c1de0837f106d2dbbfd5d0720a5d059d1c66b42b580965c8f06bb1db684be8783538b684092648c981294bf817869f743a066538771dbecb293df78f765e00 + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: ^3.0.0 + checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 + languageName: node + linkType: hard + +"shell-quote@npm:^1.7.3, shell-quote@npm:^1.8.1": + version: 1.8.1 + resolution: "shell-quote@npm:1.8.1" + checksum: 5f01201f4ef504d4c6a9d0d283fa17075f6770bfbe4c5850b074974c68062f37929ca61700d95ad2ac8822e14e8c4b990ca0e6e9272e64befd74ce5e19f0736b + languageName: node + linkType: hard + +"shelljs@npm:^0.8.5": + version: 0.8.5 + resolution: "shelljs@npm:0.8.5" + dependencies: + glob: ^7.0.0 + interpret: ^1.0.0 + rechoir: ^0.6.2 + bin: + shjs: bin/shjs + checksum: 7babc46f732a98f4c054ec1f048b55b9149b98aa2da32f6cf9844c434b43c6251efebd6eec120937bd0999e13811ebd45efe17410edb3ca938f82f9381302748 + languageName: node + linkType: hard + +"shiki@npm:^0.14.1": + version: 0.14.6 + resolution: "shiki@npm:0.14.6" + dependencies: + ansi-sequence-parser: ^1.1.0 + jsonc-parser: ^3.2.0 + vscode-oniguruma: ^1.7.0 + vscode-textmate: ^8.0.0 + checksum: 24d9e29f93546118f1c07659e8a38f7dbf57b06479a0a9245e0823f7c988c825be53ad0b83a820e2eda5edbf3f0c6d17fad398b825130de1c11973e0bd7075fc + languageName: node + linkType: hard + +"side-channel@npm:^1.0.4": + version: 1.0.4 + resolution: "side-channel@npm:1.0.4" + dependencies: + call-bind: ^1.0.0 + get-intrinsic: ^1.0.2 + object-inspect: ^1.9.0 + checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 + languageName: node + linkType: hard + +"sinon@npm:^17.0.1": + version: 17.0.1 + resolution: "sinon@npm:17.0.1" + dependencies: + "@sinonjs/commons": ^3.0.0 + "@sinonjs/fake-timers": ^11.2.2 + "@sinonjs/samsam": ^8.0.0 + diff: ^5.1.0 + nise: ^5.1.5 + supports-color: ^7.2.0 + checksum: a807c2997d6eabdcaa4409df9fd9816a3e839f96d7e5d76610a33f5e1b60cf37616c6288f0f580262da17ea4ee626c6d1600325bf423e30c5a7f0d9a203e26c0 + languageName: node + linkType: hard + +"sirv@npm:^2.0.3": + version: 2.0.3 + resolution: "sirv@npm:2.0.3" + dependencies: + "@polka/url": ^1.0.0-next.20 + mrmime: ^1.0.0 + totalist: ^3.0.0 + checksum: e2dfd4c97735a6ad6d842d0eec2cd9e3919ff0e46f0d228248c5753ad4b70b832711e77e1259c031c439cdb08303cc54d923685c92b0e890145cc733af7c5568 + languageName: node + linkType: hard + +"sisteransi@npm:^1.0.5": + version: 1.0.5 + resolution: "sisteransi@npm:1.0.5" + checksum: aba6438f46d2bfcef94cf112c835ab395172c75f67453fe05c340c770d3c402363018ae1ab4172a1026a90c47eaccf3af7b6ff6fa749a680c2929bd7fa2b37a4 + languageName: node + linkType: hard + +"sitemap@npm:^7.1.1": + version: 7.1.1 + resolution: "sitemap@npm:7.1.1" + dependencies: + "@types/node": ^17.0.5 + "@types/sax": ^1.2.1 + arg: ^5.0.0 + sax: ^1.2.4 + bin: + sitemap: dist/cli.js + checksum: 87a6d21b0d4a33b8c611d3bb8543d02b813c0ebfce014213ef31849b5c1439005644f19ad1593ec89815f6101355f468c9a02c251d09aa03f6fddd17e23c4be4 + languageName: node + linkType: hard + +"skin-tone@npm:^2.0.0": + version: 2.0.0 + resolution: "skin-tone@npm:2.0.0" + dependencies: + unicode-emoji-modifier-base: ^1.0.0 + checksum: 19de157586b8019cacc55eb25d9d640f00fc02415761f3e41a4527142970fd4e7f6af0333bc90e879858766c20a976107bb386ffd4c812289c01d51f2c8d182c + languageName: node + linkType: hard + +"slash@npm:^3.0.0": + version: 3.0.0 + resolution: "slash@npm:3.0.0" + checksum: 94a93fff615f25a999ad4b83c9d5e257a7280c90a32a7cb8b4a87996e4babf322e469c42b7f649fd5796edd8687652f3fb452a86dc97a816f01113183393f11c + languageName: node + linkType: hard + +"slash@npm:^4.0.0": + version: 4.0.0 + resolution: "slash@npm:4.0.0" + checksum: da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d + languageName: node + linkType: hard + +"slash@npm:^5.1.0": + version: 5.1.0 + resolution: "slash@npm:5.1.0" + checksum: 70434b34c50eb21b741d37d455110258c42d2cf18c01e6518aeb7299f3c6e626330c889c0c552b5ca2ef54a8f5a74213ab48895f0640717cacefeef6830a1ba4 + languageName: node + linkType: hard + +"slice-ansi@npm:^4.0.0": + version: 4.0.0 + resolution: "slice-ansi@npm:4.0.0" + dependencies: + ansi-styles: ^4.0.0 + astral-regex: ^2.0.0 + is-fullwidth-code-point: ^3.0.0 + checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: b5167a7142c1da704c0e3af85c402002b597081dd9575031a90b4f229ca5678e9a36e8a374f1814c8156a725d17008ae3bde63b92f9cfd132526379e580bec8b + languageName: node + linkType: hard + +"smol-toml@npm:^1.1.2": + version: 1.1.3 + resolution: "smol-toml@npm:1.1.3" + checksum: 7948c0823b3d8db9ebf7d6dc706f75ea2bc55fa0233e6fccabc2ae3be0f1410da4617d9e3db0708a6434cfd35e13c2bc453300fa4ab11dde3da5df1c166feb39 + languageName: node + linkType: hard + +"snake-case@npm:^3.0.4": + version: 3.0.4 + resolution: "snake-case@npm:3.0.4" + dependencies: + dot-case: ^3.0.4 + tslib: ^2.0.3 + checksum: 0a7a79900bbb36f8aaa922cf111702a3647ac6165736d5dc96d3ef367efc50465cac70c53cd172c382b022dac72ec91710608e5393de71f76d7142e6fd80e8a3 + languageName: node + linkType: hard + +"sockjs@npm:^0.3.24": + version: 0.3.24 + resolution: "sockjs@npm:0.3.24" + dependencies: + faye-websocket: ^0.11.3 + uuid: ^8.3.2 + websocket-driver: ^0.7.4 + checksum: 355309b48d2c4e9755349daa29cea1c0d9ee23e49b983841c6bf7a20276b00d3c02343f9f33f26d2ee8b261a5a02961b52a25c8da88b2538c5b68d3071b4934c + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.1, socks-proxy-agent@npm:^8.0.2": + version: 8.0.2 + resolution: "socks-proxy-agent@npm:8.0.2" + dependencies: + agent-base: ^7.0.2 + debug: ^4.3.4 + socks: ^2.7.1 + checksum: 4fb165df08f1f380881dcd887b3cdfdc1aba3797c76c1e9f51d29048be6e494c5b06d68e7aea2e23df4572428f27a3ec22b3d7c75c570c5346507433899a4b6d + languageName: node + linkType: hard + +"socks@npm:^2.7.1": + version: 2.7.1 + resolution: "socks@npm:2.7.1" + dependencies: + ip: ^2.0.0 + smart-buffer: ^4.2.0 + checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 + languageName: node + linkType: hard + +"solc@npm:0.8.26": + version: 0.8.26 + resolution: "solc@npm:0.8.26" + dependencies: + command-exists: ^1.2.8 + commander: ^8.1.0 + follow-redirects: ^1.12.1 + js-sha3: 0.8.0 + memorystream: ^0.3.1 + semver: ^5.5.0 + tmp: 0.0.33 + bin: + solcjs: solc.js + checksum: e3eaeac76e60676377b357af8f3919d4c8c6a74b74112b49279fe8c74a3dfa1de8afe4788689fc307453bde336edc8572988d2cf9e909f84d870420eb640400c + languageName: node + linkType: hard + +"sort-css-media-queries@npm:2.1.0": + version: 2.1.0 + resolution: "sort-css-media-queries@npm:2.1.0" + checksum: 25cb8f08b148a2ed83d0bc1cf20ddb888d3dee2a3c986896099a21b28b999d5cca3e46a9ef64381bb36fca0fc820471713f2e8af2729ecc6e108ab2b3b315ea9 + languageName: node + linkType: hard + +"sort-css-media-queries@npm:2.2.0": + version: 2.2.0 + resolution: "sort-css-media-queries@npm:2.2.0" + checksum: c090c9a27be40f3e50f5f9bc9d85a8af0e2c5152565eca34bdb028d952749bce169bc5abef21a5a385ca6221a0869640c9faf58f082ac46de9085ebdb506291f + languageName: node + linkType: hard + +"source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 4eb0cd997cdf228bc253bcaff9340afeb706176e64868ecd20efbe6efea931465f43955612346d6b7318789e5265bdc419bc7669c1cebe3db0eb255f57efa76b + languageName: node + linkType: hard + +"source-map-js@npm:^1.0.2": + version: 1.0.2 + resolution: "source-map-js@npm:1.0.2" + checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c + languageName: node + linkType: hard + +"source-map-support@npm:^0.5.13, source-map-support@npm:~0.5.20": + version: 0.5.21 + resolution: "source-map-support@npm:0.5.21" + dependencies: + buffer-from: ^1.0.0 + source-map: ^0.6.0 + checksum: 43e98d700d79af1d36f859bdb7318e601dfc918c7ba2e98456118ebc4c4872b327773e5a1df09b0524e9e5063bb18f0934538eace60cca2710d1fa687645d137 + languageName: node + linkType: hard + +"source-map@npm:^0.5.0": + version: 0.5.7 + resolution: "source-map@npm:0.5.7" + checksum: 5dc2043b93d2f194142c7f38f74a24670cd7a0063acdaf4bf01d2964b402257ae843c2a8fa822ad5b71013b5fcafa55af7421383da919752f22ff488bc553f4d + languageName: node + linkType: hard + +"source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.0, source-map@npm:~0.6.1": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 + languageName: node + linkType: hard + +"source-map@npm:^0.7.0, source-map@npm:^0.7.3, source-map@npm:^0.7.4": + version: 0.7.4 + resolution: "source-map@npm:0.7.4" + checksum: 01cc5a74b1f0e1d626a58d36ad6898ea820567e87f18dfc9d24a9843a351aaa2ec09b87422589906d6ff1deed29693e176194dc88bcae7c9a852dc74b311dbf5 + languageName: node + linkType: hard + +"space-separated-tokens@npm:^1.0.0": + version: 1.1.5 + resolution: "space-separated-tokens@npm:1.1.5" + checksum: 8ef68f1cfa8ccad316b7f8d0df0919d0f1f6d32101e8faeee34ea3a923ce8509c1ad562f57388585ee4951e92d27afa211ed0a077d3d5995b5ba9180331be708 + languageName: node + linkType: hard + +"space-separated-tokens@npm:^2.0.0": + version: 2.0.2 + resolution: "space-separated-tokens@npm:2.0.2" + checksum: 202e97d7ca1ba0758a0aa4fe226ff98142073bcceeff2da3aad037968878552c3bbce3b3231970025375bbba5aee00c5b8206eda408da837ab2dc9c0f26be990 + languageName: node + linkType: hard + +"spdy-transport@npm:^3.0.0": + version: 3.0.0 + resolution: "spdy-transport@npm:3.0.0" + dependencies: + debug: ^4.1.0 + detect-node: ^2.0.4 + hpack.js: ^2.1.6 + obuf: ^1.1.2 + readable-stream: ^3.0.6 + wbuf: ^1.7.3 + checksum: 0fcaad3b836fb1ec0bdd39fa7008b9a7a84a553f12be6b736a2512613b323207ffc924b9551cef0378f7233c85916cff1118652e03a730bdb97c0e042243d56c + languageName: node + linkType: hard + +"spdy@npm:^4.0.2": + version: 4.0.2 + resolution: "spdy@npm:4.0.2" + dependencies: + debug: ^4.1.0 + handle-thing: ^2.0.0 + http-deceiver: ^1.2.7 + select-hose: ^2.0.0 + spdy-transport: ^3.0.0 + checksum: 2c739d0ff6f56ad36d2d754d0261d5ec358457bea7cbf77b1b05b0c6464f2ce65b85f196305f50b7bd9120723eb94bae9933466f28e67e5cd8cde4e27f1d75f8 + languageName: node + linkType: hard + +"sprintf-js@npm:^1.0.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 + languageName: node + linkType: hard + +"sprintf-js@npm:~1.0.2": + version: 1.0.3 + resolution: "sprintf-js@npm:1.0.3" + checksum: 19d79aec211f09b99ec3099b5b2ae2f6e9cdefe50bc91ac4c69144b6d3928a640bb6ae5b3def70c2e85a2c3d9f5ec2719921e3a59d3ca3ef4b2fd1a4656a0df3 + languageName: node + linkType: hard + +"srcset@npm:^4.0.0": + version: 4.0.0 + resolution: "srcset@npm:4.0.0" + checksum: aceb898c9281101ef43bfbf96bf04dfae828e1bf942a45df6fad74ae9f8f0a425f4bca1480e0d22879beb40dd2bc6947e0e1e5f4d307a714666196164bc5769d + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.5 + resolution: "ssri@npm:10.0.5" + dependencies: + minipass: ^7.0.3 + checksum: 0a31b65f21872dea1ed3f7c200d7bc1c1b91c15e419deca14f282508ba917cbb342c08a6814c7f68ca4ca4116dd1a85da2bbf39227480e50125a1ceffeecb750 + languageName: node + linkType: hard + +"stable@npm:^0.1.8": + version: 0.1.8 + resolution: "stable@npm:0.1.8" + checksum: 2ff482bb100285d16dd75cd8f7c60ab652570e8952c0bfa91828a2b5f646a0ff533f14596ea4eabd48bb7f4aeea408dce8f8515812b975d958a4cc4fa6b9dfeb + languageName: node + linkType: hard + +"stacktrace-parser@npm:^0.1.10": + version: 0.1.10 + resolution: "stacktrace-parser@npm:0.1.10" + dependencies: + type-fest: ^0.7.1 + checksum: f4fbddfc09121d91e587b60de4beb4941108e967d71ad3a171812dc839b010ca374d064ad0a296295fed13acd103609d99a4224a25b4e67de13cae131f1901ee + languageName: node + linkType: hard + +"state-toggle@npm:^1.0.0": + version: 1.0.3 + resolution: "state-toggle@npm:1.0.3" + checksum: 17398af928413e8d8b866cf0c81fd1b1348bb7d65d8983126ff6ff2317a80d6ee023484fba0c54d8169f5aa544f125434a650ae3a71eddc935cae307d4692b4f + languageName: node + linkType: hard + +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb + languageName: node + linkType: hard + +"statuses@npm:>= 1.4.0 < 2, statuses@npm:>= 1.5.0 < 2, statuses@npm:^1.5.0": + version: 1.5.0 + resolution: "statuses@npm:1.5.0" + checksum: c469b9519de16a4bb19600205cffb39ee471a5f17b82589757ca7bd40a8d92ebb6ed9f98b5a540c5d302ccbc78f15dc03cc0280dd6e00df1335568a5d5758a5c + languageName: node + linkType: hard + +"std-env@npm:^3.0.1": + version: 3.6.0 + resolution: "std-env@npm:3.6.0" + checksum: ec344e93af17fd1b71eb28aeb4712f72790b9f2363981fc91ad1a91c9c7967c1ab89271819242d1b3bdbd57f10ac8ef0559d561ccf081a5377f9b3cd8c9b2259 + languageName: node + linkType: hard + +"stream-read-all@npm:^3.0.1": + version: 3.0.1 + resolution: "stream-read-all@npm:3.0.1" + checksum: 40d3c286837f1b1ae7e8105959804ad42fda00f2c087722d981cb1c9fbbea892b8a0a7ca1cf6a016c96770151a6201a3da5c8b66fe35e35106b52a5e9ab90e3e + 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" + dependencies: + fast-fifo: ^1.1.0 + queue-tick: ^1.0.1 + checksum: 37a245f5cee4c33fcb8b018ccb935bad6eab423f05b0d14d018e63dbd2670bb109a69442e961a195b750c2c774f613c19476d11bd727d645eedb655d2dba234b + languageName: node + linkType: hard + +"string-format@npm:^2.0.0": + version: 2.0.0 + resolution: "string-format@npm:2.0.0" + checksum: dada2ef95f6d36c66562c673d95315f80457fa7dce2f3609a2e75d1190b98c88319028cf0a5b6c043d01c18d581b2641579f79480584ba030d6ac6fceb30bc55 + languageName: node + linkType: hard + +"string-range@npm:~1.2, string-range@npm:~1.2.1": + version: 1.2.2 + resolution: "string-range@npm:1.2.2" + checksum: 7118cc83a7e63fca5fd8bef9b61464bfc51197b5f6dc475c9e1d24a93ce02fa27f7adb4cd7adac5daf599bde442b383608078f9b051bddb108d3b45840923097 + languageName: node + linkType: hard + +"string-to-stream@npm:^3.0.1": + version: 3.0.1 + resolution: "string-to-stream@npm:3.0.1" + dependencies: + readable-stream: ^3.4.0 + checksum: e8ac7f7497f8f101196e39dd529e98bb97165c532cc4cae5003083a420db62f46ffd67ddff7112b45f9f8d0f9ff1cc6cda9b06362236d43fa6b1685e8b0d446e + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: ^8.0.0 + is-fullwidth-code-point: ^3.0.0 + strip-ansi: ^6.0.1 + checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: ^0.2.0 + emoji-regex: ^9.2.2 + strip-ansi: ^7.0.1 + checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193 + languageName: node + linkType: hard + +"string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: ~5.2.0 + checksum: 8417646695a66e73aefc4420eb3b84cc9ffd89572861fe004e6aeb13c7bc00e2f616247505d2dbbef24247c372f70268f594af7126f43548565c68c117bdeb56 + languageName: node + linkType: hard + +"string_decoder@npm:~0.10.x": + version: 0.10.31 + resolution: "string_decoder@npm:0.10.31" + checksum: fe00f8e303647e5db919948ccb5ce0da7dea209ab54702894dd0c664edd98e5d4df4b80d6fabf7b9e92b237359d21136c95bf068b2f7760b772ca974ba970202 + languageName: node + linkType: hard + +"string_decoder@npm:~1.1.1": + version: 1.1.1 + resolution: "string_decoder@npm:1.1.1" + dependencies: + safe-buffer: ~5.1.0 + checksum: 9ab7e56f9d60a28f2be697419917c50cac19f3e8e6c28ef26ed5f4852289fe0de5d6997d29becf59028556f2c62983790c1d9ba1e2a3cc401768ca12d5183a5b + languageName: node + linkType: hard + +"stringify-entities@npm:^4.0.0": + version: 4.0.3 + resolution: "stringify-entities@npm:4.0.3" + dependencies: + character-entities-html4: ^2.0.0 + character-entities-legacy: ^3.0.0 + checksum: 59e8f523b403bf7d415690e72ae52982decd6ea5426bd8b3f5c66225ddde73e766c0c0d91627df082d0794e30b19dd907ffb5864cef3602e4098d6777d7ca3c2 + languageName: node + linkType: hard + +"stringify-object@npm:^3.3.0": + version: 3.3.0 + resolution: "stringify-object@npm:3.3.0" + dependencies: + get-own-enumerable-property-symbols: ^3.0.0 + is-obj: ^1.0.1 + is-regexp: ^1.0.0 + checksum: 6827a3f35975cfa8572e8cd3ed4f7b262def260af18655c6fde549334acdac49ddba69f3c861ea5a6e9c5a4990fe4ae870b9c0e6c31019430504c94a83b7a154 + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: ^5.0.1 + checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: ^6.0.1 + checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d + languageName: node + linkType: hard + +"strip-bom-string@npm:^1.0.0": + version: 1.0.0 + resolution: "strip-bom-string@npm:1.0.0" + checksum: 5635a3656d8512a2c194d6c8d5dee7ef0dde6802f7be9413b91e201981ad4132506656d9cf14137f019fd50f0269390d91c7f6a2601b1bee039a4859cfce4934 + languageName: node + linkType: hard + +"strip-final-newline@npm:^2.0.0": + version: 2.0.0 + resolution: "strip-final-newline@npm:2.0.0" + checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 + languageName: node + linkType: hard + +"strip-hex-prefix@npm:1.0.0": + version: 1.0.0 + resolution: "strip-hex-prefix@npm:1.0.0" + dependencies: + is-hex-prefixed: 1.0.0 + checksum: 4cafe7caee1d281d3694d14920fd5d3c11adf09371cef7e2ccedd5b83efd9e9bd2219b5d6ce6e809df6e0f437dc9d30db1192116580875698aad164a6d6b285b + languageName: node + linkType: hard + +"strip-json-comments@npm:3.1.1, strip-json-comments@npm:^3.1.1": + version: 3.1.1 + resolution: "strip-json-comments@npm:3.1.1" + checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 + languageName: node + linkType: hard + +"strip-json-comments@npm:~2.0.1": + version: 2.0.1 + resolution: "strip-json-comments@npm:2.0.1" + checksum: 1074ccb63270d32ca28edfb0a281c96b94dc679077828135141f27d52a5a398ef5e78bcf22809d23cadc2b81dfbe345eb5fd8699b385c8b1128907dec4a7d1e1 + languageName: node + linkType: hard + +"style-to-object@npm:0.3.0, style-to-object@npm:^0.3.0": + version: 0.3.0 + resolution: "style-to-object@npm:0.3.0" + dependencies: + inline-style-parser: 0.1.1 + checksum: 4d7084015207f2a606dfc10c29cb5ba569f2fe8005551df7396110dd694d6ff650f2debafa95bd5d147dfb4ca50f57868e2a7f91bf5d11ef734fe7ccbd7abf59 + languageName: node + linkType: hard + +"style-to-object@npm:^0.4.0": + version: 0.4.4 + resolution: "style-to-object@npm:0.4.4" + dependencies: + inline-style-parser: 0.1.1 + checksum: 41656c06f93ac0a7ac260ebc2f9d09a8bd74b8ec1836f358cc58e169235835a3a356977891d2ebbd76f0e08a53616929069199f9cce543214d3dc98346e19c9a + languageName: node + linkType: hard + +"style-to-object@npm:^1.0.0": + version: 1.0.5 + resolution: "style-to-object@npm:1.0.5" + dependencies: + inline-style-parser: 0.2.2 + checksum: 6201063204b6a94645f81b189452b2ca3e63d61867ec48523f4d52609c81e96176739fa12020d97fbbf023efb57a6f7ec3a15fb3a7fb7eb3ffea0b52b9dd6b8c + languageName: node + linkType: hard + +"stylehacks@npm:^5.1.1": + version: 5.1.1 + resolution: "stylehacks@npm:5.1.1" + dependencies: + browserslist: ^4.21.4 + postcss-selector-parser: ^6.0.4 + peerDependencies: + postcss: ^8.2.15 + checksum: 11175366ef52de65bf06cefba0ddc9db286dc3a1451fd2989e74c6ea47091a02329a4bf6ce10b1a36950056927b6bbbe47c5ab3a1f4c7032df932d010fbde5a2 + languageName: node + linkType: hard + +"stylehacks@npm:^6.1.1": + version: 6.1.1 + resolution: "stylehacks@npm:6.1.1" + dependencies: + browserslist: ^4.23.0 + postcss-selector-parser: ^6.0.16 + peerDependencies: + postcss: ^8.4.31 + checksum: 7bef69822280a23817caa43969de76d77ba34042e9f1f7baaeda8f22b1d8c20f1f839ad028552c169e158e387830f176feccd0324b07ef6ec657cba1dd0b2466 + languageName: node + linkType: hard + +"superstruct@npm:^1.0.3": + version: 1.0.3 + resolution: "superstruct@npm:1.0.3" + checksum: 761790bb111e6e21ddd608299c252f3be35df543263a7ebbc004e840d01fcf8046794c274bcb351bdf3eae4600f79d317d085cdbb19ca05803a4361840cc9bb1 + languageName: node + linkType: hard + +"supports-color@npm:8.1.1, supports-color@npm:^8.0.0": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: ^4.0.0 + checksum: c052193a7e43c6cdc741eb7f378df605636e01ad434badf7324f17fb60c69a880d8d8fcdcb562cf94c2350e57b937d7425ab5b8326c67c2adc48f7c87c1db406 + languageName: node + linkType: hard + +"supports-color@npm:^5.3.0": + version: 5.5.0 + resolution: "supports-color@npm:5.5.0" + dependencies: + has-flag: ^3.0.0 + checksum: 95f6f4ba5afdf92f495b5a912d4abee8dcba766ae719b975c56c084f5004845f6f5a5f7769f52d53f40e21952a6d87411bafe34af4a01e65f9926002e38e1dac + languageName: node + linkType: hard + +"supports-color@npm:^7.1.0, supports-color@npm:^7.2.0": + version: 7.2.0 + resolution: "supports-color@npm:7.2.0" + dependencies: + has-flag: ^4.0.0 + checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a + languageName: node + linkType: hard + +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae + languageName: node + linkType: hard + +"svg-parser@npm:^2.0.4": + version: 2.0.4 + resolution: "svg-parser@npm:2.0.4" + checksum: b3de6653048212f2ae7afe4a423e04a76ec6d2d06e1bf7eacc618a7c5f7df7faa5105561c57b94579ec831fbbdbf5f190ba56a9205ff39ed13eabdf8ab086ddf + languageName: node + linkType: hard + +"svgo@npm:^2.7.0, svgo@npm:^2.8.0": + version: 2.8.0 + resolution: "svgo@npm:2.8.0" + dependencies: + "@trysound/sax": 0.2.0 + commander: ^7.2.0 + css-select: ^4.1.3 + css-tree: ^1.1.3 + csso: ^4.2.0 + picocolors: ^1.0.0 + stable: ^0.1.8 + bin: + svgo: bin/svgo + checksum: b92f71a8541468ffd0b81b8cdb36b1e242eea320bf3c1a9b2c8809945853e9d8c80c19744267eb91cabf06ae9d5fff3592d677df85a31be4ed59ff78534fa420 + languageName: node + linkType: hard + +"svgo@npm:^3.0.2, svgo@npm:^3.2.0": + version: 3.3.2 + resolution: "svgo@npm:3.3.2" + dependencies: + "@trysound/sax": 0.2.0 + commander: ^7.2.0 + css-select: ^5.1.0 + css-tree: ^2.3.1 + css-what: ^6.1.0 + csso: ^5.0.5 + picocolors: ^1.0.0 + bin: + svgo: ./bin/svgo + checksum: a3f8aad597dec13ab24e679c4c218147048dc1414fe04e99447c5f42a6e077b33d712d306df84674b5253b98c9b84dfbfb41fdd08552443b04946e43d03e054e + languageName: node + linkType: hard + +"synckit@npm:^0.8.6": + version: 0.8.8 + resolution: "synckit@npm:0.8.8" + dependencies: + "@pkgr/core": ^0.1.0 + tslib: ^2.6.2 + checksum: 9ed5d33abb785f5f24e2531efd53b2782ca77abf7912f734d170134552b99001915531be5a50297aa45c5701b5c9041e8762e6cd7a38e41e2461c1e7fccdedf8 + languageName: node + linkType: hard + +"table-layout@npm:^1.0.2": + version: 1.0.2 + resolution: "table-layout@npm:1.0.2" + dependencies: + array-back: ^4.0.1 + deep-extend: ~0.6.0 + typical: ^5.2.0 + wordwrapjs: ^4.0.0 + checksum: 8f41b5671f101a5195747ec1727b1d35ea2cd5bf85addda11cc2f4b36892db9696ce3c2c7334b5b8a122505b34d19135fede50e25678df71b0439e0704fd953f + languageName: node + linkType: hard + +"table-layout@npm:^3.0.0": + version: 3.0.2 + resolution: "table-layout@npm:3.0.2" + dependencies: + "@75lb/deep-merge": ^1.1.1 + array-back: ^6.2.2 + command-line-args: ^5.2.1 + command-line-usage: ^7.0.0 + stream-read-all: ^3.0.1 + typical: ^7.1.1 + wordwrapjs: ^5.1.0 + bin: + table-layout: bin/cli.js + checksum: 2d4c538f224e64321d35788dbf78305cc1d138a3508e1a29f33e4f6b00bd082990a45dc85fd92948213f48ed8c0b3599155c2a05de412661ff020635e0db3762 + languageName: node + linkType: hard + +"tapable@npm:^1.0.0": + version: 1.1.3 + resolution: "tapable@npm:1.1.3" + checksum: 53ff4e7c3900051c38cc4faab428ebfd7e6ad0841af5a7ac6d5f3045c5b50e88497bfa8295b4b3fbcadd94993c9e358868b78b9fb249a76cb8b018ac8dccafd7 + languageName: node + linkType: hard + +"tapable@npm:^2.0.0, tapable@npm:^2.1.1, tapable@npm:^2.2.0": + version: 2.2.1 + resolution: "tapable@npm:2.2.1" + checksum: 3b7a1b4d86fa940aad46d9e73d1e8739335efd4c48322cb37d073eb6f80f5281889bf0320c6d8ffcfa1a0dd5bfdbd0f9d037e252ef972aca595330538aac4d51 + languageName: node + linkType: hard + +"tar-fs@npm:3.0.5": + version: 3.0.5 + resolution: "tar-fs@npm:3.0.5" + dependencies: + bare-fs: ^2.1.1 + bare-path: ^2.1.0 + pump: ^3.0.0 + tar-stream: ^3.1.5 + dependenciesMeta: + bare-fs: + optional: true + bare-path: + optional: true + checksum: e31c7e3e525fec0afecdec1cac58071809e396187725f2eba442f08a4c5649c8cd6b7ce25982f9a91bb0f055628df47c08177dd2ea4f5dafd3c22f42f8da8f00 + languageName: node + linkType: hard + +"tar-stream@npm:^3.1.5": + version: 3.1.6 + resolution: "tar-stream@npm:3.1.6" + dependencies: + b4a: ^1.6.4 + fast-fifo: ^1.2.0 + streamx: ^2.15.0 + checksum: f3627f918581976e954ff03cb8d370551053796b82564f8c7ca8fac84c48e4d042026d0854fc222171a34ff9c682b72fae91be9c9b0a112d4c54f9e4f443e9c5 + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.1.2": + version: 6.2.0 + resolution: "tar@npm:6.2.0" + dependencies: + chownr: ^2.0.0 + fs-minipass: ^2.0.0 + minipass: ^5.0.0 + minizlib: ^2.1.1 + mkdirp: ^1.0.3 + yallist: ^4.0.0 + checksum: db4d9fe74a2082c3a5016630092c54c8375ff3b280186938cfd104f2e089c4fd9bad58688ef6be9cf186a889671bf355c7cda38f09bbf60604b281715ca57f5c + languageName: node + linkType: hard + +"terser-webpack-plugin@npm:^5.3.10": + version: 5.3.10 + resolution: "terser-webpack-plugin@npm:5.3.10" + dependencies: + "@jridgewell/trace-mapping": ^0.3.20 + jest-worker: ^27.4.5 + schema-utils: ^3.1.1 + serialize-javascript: ^6.0.1 + terser: ^5.26.0 + peerDependencies: + webpack: ^5.1.0 + peerDependenciesMeta: + "@swc/core": + optional: true + esbuild: + optional: true + uglify-js: + optional: true + checksum: bd6e7596cf815f3353e2a53e79cbdec959a1b0276f5e5d4e63e9d7c3c5bb5306df567729da287d1c7b39d79093e56863c569c42c6c24cc34c76aa313bd2cbcea + languageName: node + linkType: hard + +"terser-webpack-plugin@npm:^5.3.3, terser-webpack-plugin@npm:^5.3.7, terser-webpack-plugin@npm:^5.3.9": + version: 5.3.9 + resolution: "terser-webpack-plugin@npm:5.3.9" + dependencies: + "@jridgewell/trace-mapping": ^0.3.17 + jest-worker: ^27.4.5 + schema-utils: ^3.1.1 + serialize-javascript: ^6.0.1 + terser: ^5.16.8 + peerDependencies: + webpack: ^5.1.0 + peerDependenciesMeta: + "@swc/core": + optional: true + esbuild: + optional: true + uglify-js: + optional: true + checksum: 41705713d6f9cb83287936b21e27c658891c78c4392159f5148b5623f0e8c48559869779619b058382a4c9758e7820ea034695e57dc7c474b4962b79f553bc5f + languageName: node + linkType: hard + +"terser@npm:^5.10.0, terser@npm:^5.15.1, terser@npm:^5.16.8": + version: 5.26.0 + resolution: "terser@npm:5.26.0" + dependencies: + "@jridgewell/source-map": ^0.3.3 + acorn: ^8.8.2 + commander: ^2.20.0 + source-map-support: ~0.5.20 + bin: + terser: bin/terser + checksum: 02a9bb896f04df828025af8f0eced36c315d25d310b6c2418e7dad2bed19ddeb34a9cea9b34e7c24789830fa51e1b6a9be26679980987a9c817a7e6d9cd4154b + languageName: node + linkType: hard + +"terser@npm:^5.26.0": + version: 5.27.0 + resolution: "terser@npm:5.27.0" + dependencies: + "@jridgewell/source-map": ^0.3.3 + acorn: ^8.8.2 + commander: ^2.20.0 + source-map-support: ~0.5.20 + bin: + terser: bin/terser + checksum: c165052cfea061e8512e9b9ba42a098c2ff6382886ae122b040fd5b6153443070cc2dcb4862269f1669c09c716763e856125a355ff984aa72be525d6fffd8729 + languageName: node + linkType: hard + +"text-table@npm:^0.2.0": + version: 0.2.0 + resolution: "text-table@npm:0.2.0" + checksum: b6937a38c80c7f84d9c11dd75e49d5c44f71d95e810a3250bd1f1797fc7117c57698204adf676b71497acc205d769d65c16ae8fa10afad832ae1322630aef10a + languageName: node + linkType: hard + +"thingies@npm:^1.11.1": + version: 1.15.0 + resolution: "thingies@npm:1.15.0" + peerDependencies: + tslib: ^2 + checksum: 9721bc0cbcf1565ba1abd70cfe5141a638c88dded74abb24d9b21749e16034af37dfa68edd37e7d1bb1b1c9c8bfb301c4699a8e4bc998a3a9c18052edb829bb2 + languageName: node + linkType: hard + +"through@npm:^2.3.8": + version: 2.3.8 + resolution: "through@npm:2.3.8" + checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd + languageName: node + linkType: hard + +"thunky@npm:^1.0.2": + version: 1.1.0 + resolution: "thunky@npm:1.1.0" + checksum: 993096c472b6b8f30e29dc777a8d17720e4cab448375041f20c0cb802a09a7fb2217f2a3e8cdc11851faa71c957e2db309357367fc9d7af3cb7a4d00f4b66034 + languageName: node + linkType: hard + +"tiny-invariant@npm:^1.0.2": + version: 1.3.1 + resolution: "tiny-invariant@npm:1.3.1" + checksum: 872dbd1ff20a21303a2fd20ce3a15602cfa7fcf9b228bd694a52e2938224313b5385a1078cb667ed7375d1612194feaca81c4ecbe93121ca1baebe344de4f84c + languageName: node + linkType: hard + +"tiny-warning@npm:^1.0.0": + version: 1.0.3 + resolution: "tiny-warning@npm:1.0.3" + checksum: da62c4acac565902f0624b123eed6dd3509bc9a8d30c06e017104bedcf5d35810da8ff72864400ad19c5c7806fc0a8323c68baf3e326af7cb7d969f846100d71 + languageName: node + linkType: hard + +"tmp@npm:0.0.33": + version: 0.0.33 + resolution: "tmp@npm:0.0.33" + dependencies: + os-tmpdir: ~1.0.2 + checksum: 902d7aceb74453ea02abbf58c203f4a8fc1cead89b60b31e354f74ed5b3fb09ea817f94fb310f884a5d16987dd9fa5a735412a7c2dd088dd3d415aa819ae3a28 + languageName: node + linkType: hard + +"to-fast-properties@npm:^2.0.0": + version: 2.0.0 + resolution: "to-fast-properties@npm:2.0.0" + checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 + languageName: node + linkType: hard + +"to-readable-stream@npm:^1.0.0": + version: 1.0.0 + resolution: "to-readable-stream@npm:1.0.0" + checksum: 2bd7778490b6214a2c40276065dd88949f4cf7037ce3964c76838b8cb212893aeb9cceaaf4352a4c486e3336214c350270f3263e1ce7a0c38863a715a4d9aeb5 + languageName: node + linkType: hard + +"to-regex-range@npm:^5.0.1": + version: 5.0.1 + resolution: "to-regex-range@npm:5.0.1" + dependencies: + is-number: ^7.0.0 + checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed + languageName: node + linkType: hard + +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 + languageName: node + linkType: hard + +"toml@npm:^3.0.0": + version: 3.0.0 + resolution: "toml@npm:3.0.0" + checksum: 5d7f1d8413ad7780e9bdecce8ea4c3f5130dd53b0a4f2e90b93340979a137739879d7b9ce2ce05c938b8cc828897fe9e95085197342a1377dd8850bf5125f15f + languageName: node + linkType: hard + +"totalist@npm:^3.0.0": + version: 3.0.1 + resolution: "totalist@npm:3.0.1" + checksum: 5132d562cf88ff93fd710770a92f31dbe67cc19b5c6ccae2efc0da327f0954d211bbfd9456389655d726c624f284b4a23112f56d1da931ca7cfabbe1f45e778a + languageName: node + linkType: hard + +"tr46@npm:^3.0.0": + version: 3.0.0 + resolution: "tr46@npm:3.0.0" + dependencies: + punycode: ^2.1.1 + checksum: 44c3cc6767fb800490e6e9fd64fd49041aa4e49e1f6a012b34a75de739cc9ed3a6405296072c1df8b6389ae139c5e7c6496f659cfe13a04a4bff3a1422981270 + languageName: node + linkType: hard + +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 726321c5eaf41b5002e17ffbd1fb7245999a073e8979085dacd47c4b4e8068ff5777142fc6726d6ca1fd2ff16921b48788b87225cbc57c72636f6efa8efbffe3 + languageName: node + linkType: hard + +"trim-lines@npm:^3.0.0": + version: 3.0.1 + resolution: "trim-lines@npm:3.0.1" + checksum: e241da104682a0e0d807222cc1496b92e716af4db7a002f4aeff33ae6a0024fef93165d49eab11aa07c71e1347c42d46563f91dfaa4d3fb945aa535cdead53ed + languageName: node + linkType: hard + +"trim-trailing-lines@npm:^1.0.0": + version: 1.1.4 + resolution: "trim-trailing-lines@npm:1.1.4" + checksum: 5d39d21c0d4b258667012fcd784f73129e148ea1c213b1851d8904f80499fc91df6710c94c7dd49a486a32da2b9cb86020dda79f285a9a2586cfa622f80490c2 + languageName: node + linkType: hard + +"trim@npm:0.0.1": + version: 0.0.1 + resolution: "trim@npm:0.0.1" + checksum: 2b4646dff99a222e8e1526edd4e3a43bbd925af0b8e837c340455d250157e7deefaa4da49bb891ab841e5c27b1afc5e9e32d4b57afb875d2dfcabf4e319b8f7f + languageName: node + linkType: hard + +"trough@npm:^1.0.0": + version: 1.0.5 + resolution: "trough@npm:1.0.5" + checksum: d6c8564903ed00e5258bab92134b020724dbbe83148dc72e4bf6306c03ed8843efa1bcc773fa62410dd89161ecb067432dd5916501793508a9506cacbc408e25 + languageName: node + linkType: hard + +"trough@npm:^2.0.0": + version: 2.1.0 + resolution: "trough@npm:2.1.0" + checksum: a577bb561c2b401cc0e1d9e188fcfcdf63b09b151ff56a668da12197fe97cac15e3d77d5b51f426ccfd94255744a9118e9e9935afe81a3644fa1be9783c82886 + languageName: node + linkType: hard + +"ts-api-utils@npm:^1.0.1": + version: 1.0.3 + resolution: "ts-api-utils@npm:1.0.3" + peerDependencies: + typescript: ">=4.2.0" + checksum: 441cc4489d65fd515ae6b0f4eb8690057add6f3b6a63a36073753547fb6ce0c9ea0e0530220a0b282b0eec535f52c4dfc315d35f8a4c9a91c0def0707a714ca6 + languageName: node + linkType: hard + +"ts-command-line-args@npm:^2.5.1": + version: 2.5.1 + resolution: "ts-command-line-args@npm:2.5.1" + dependencies: + chalk: ^4.1.0 + command-line-args: ^5.1.1 + command-line-usage: ^6.1.0 + string-format: ^2.0.0 + bin: + write-markdown: dist/write-markdown.js + checksum: 7c0a7582e94f1d2160e3dd379851ec4f1758bc673ccd71bae07f839f83051b6b83e0ae14325c2d04ea728e5bde7b7eacfd2ab060b8fd4b8ab29e0bbf77f6c51e + languageName: node + linkType: hard + +"ts-loader@npm:^9.5.1": + version: 9.5.1 + resolution: "ts-loader@npm:9.5.1" + dependencies: + chalk: ^4.1.0 + enhanced-resolve: ^5.0.0 + micromatch: ^4.0.0 + semver: ^7.3.4 + source-map: ^0.7.4 + peerDependencies: + typescript: "*" + webpack: ^5.0.0 + checksum: 7cf396e656d905388ea2a9b5e82f16d3c955fda8d3df2fbf219f4bee16ff50a3c995c44ae3e584634e9443f056cec70bb3151add3917ffb4588ecd7394bac0ec + languageName: node + linkType: hard + +"ts-node@npm:^10.9.1": + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" + dependencies: + "@cspotcode/source-map-support": ^0.8.0 + "@tsconfig/node10": ^1.0.7 + "@tsconfig/node12": ^1.0.7 + "@tsconfig/node14": ^1.0.0 + "@tsconfig/node16": ^1.0.2 + acorn: ^8.4.1 + acorn-walk: ^8.1.1 + arg: ^4.1.0 + create-require: ^1.1.0 + diff: ^4.0.1 + make-error: ^1.1.1 + v8-compile-cache-lib: ^3.0.1 + yn: 3.1.1 + peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true + bin: + ts-node: dist/bin.js + ts-node-cwd: dist/bin-cwd.js + ts-node-esm: dist/bin-esm.js + ts-node-script: dist/bin-script.js + ts-node-transpile-only: dist/bin-transpile.js + ts-script: dist/bin-script-deprecated.js + checksum: fde256c9073969e234526e2cfead42591b9a2aec5222bac154b0de2fa9e4ceb30efcd717ee8bc785a56f3a119bdd5aa27b333d9dbec94ed254bd26f8944c67ac + languageName: node + linkType: hard + +"tsc-multi@npm:^1.1.0": + version: 1.1.0 + resolution: "tsc-multi@npm:1.1.0" + dependencies: + debug: ^4.3.4 + fast-glob: ^3.2.12 + get-stdin: ^8.0.0 + p-all: ^3.0.0 + picocolors: ^1.0.0 + signal-exit: ^3.0.7 + string-to-stream: ^3.0.1 + superstruct: ^1.0.3 + tslib: ^2.5.0 + yargs: ^17.7.1 + peerDependencies: + typescript: ">=4.3.0" + bin: + tsc-multi: bin/tsc-multi.js + checksum: a82c0358611ac15667aa148ade33b6ad64cc0a94299fb9afc01e3e6224a994dff8812960a43643f25e4c0dac8419707027c3096d0e60bff3522591c06d5f4eeb + languageName: node + linkType: hard + +"tslib@npm:2.4.0": + version: 2.4.0 + resolution: "tslib@npm:2.4.0" + checksum: 8c4aa6a3c5a754bf76aefc38026134180c053b7bd2f81338cb5e5ebf96fefa0f417bff221592bf801077f5bf990562f6264fecbc42cd3309b33872cb6fc3b113 + languageName: node + linkType: hard + +"tslib@npm:^1.9.3": + version: 1.14.1 + resolution: "tslib@npm:1.14.1" + checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd + languageName: node + linkType: hard + +"tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.2": + version: 2.6.2 + resolution: "tslib@npm:2.6.2" + checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad + languageName: node + linkType: hard + +"tslog@npm:^4.9.2": + version: 4.9.2 + resolution: "tslog@npm:4.9.2" + checksum: 702e45647a68b127d63c5eb63a0f322af8d01f17b689127d32238d6ca2ef76889648a00b88c040430e3126acedef070022b20ebd81823879ba3766cf5188c868 + languageName: node + linkType: hard + +"tsort@npm:0.0.1": + version: 0.0.1 + resolution: "tsort@npm:0.0.1" + checksum: 581566c248690b9ea7e431e1545affb3d2cab0f5dcd0e45ddef815dfaec4864cb5f0cfd8072924dedbc0de9585ff07e3e65db60f14fab4123737b9bb6e72eacc + languageName: node + linkType: hard + +"tsscmp@npm:1.0.6": + version: 1.0.6 + resolution: "tsscmp@npm:1.0.6" + checksum: 1512384def36bccc9125cabbd4c3b0e68608d7ee08127ceaa0b84a71797263f1a01c7f82fa69be8a3bd3c1396e2965d2f7b52d581d3a5eeaf3967fbc52e3b3bf + languageName: node + linkType: hard + +"tsx@npm:^4.6.2": + version: 4.6.2 + resolution: "tsx@npm:4.6.2" + dependencies: + esbuild: ~0.18.20 + fsevents: ~2.3.3 + get-tsconfig: ^4.7.2 + dependenciesMeta: + fsevents: + optional: true + bin: + tsx: dist/cli.mjs + checksum: a9f13bdb67bfb316bbfc92303d8464323ab1b673aa93ea97271c211a8ba7c59274d4b32eeec5ad8fbd0b04260a092a3ad2116abeb6913254ba456010ff685743 + languageName: node + linkType: hard + +"tweetnacl-util@npm:^0.15.1": + version: 0.15.1 + resolution: "tweetnacl-util@npm:0.15.1" + checksum: ae6aa8a52cdd21a95103a4cc10657d6a2040b36c7a6da7b9d3ab811c6750a2d5db77e8c36969e75fdee11f511aa2b91c552496c6e8e989b6e490e54aca2864fc + languageName: node + linkType: hard + +"tweetnacl@npm:^1.0.3": + version: 1.0.3 + resolution: "tweetnacl@npm:1.0.3" + checksum: e4a57cac188f0c53f24c7a33279e223618a2bfb5fea426231991652a13247bea06b081fd745d71291fcae0f4428d29beba1b984b1f1ce6f66b06a6d1ab90645c + languageName: node + linkType: hard + +"type-check@npm:^0.4.0, type-check@npm:~0.4.0": + version: 0.4.0 + resolution: "type-check@npm:0.4.0" + dependencies: + prelude-ls: ^1.2.1 + checksum: ec688ebfc9c45d0c30412e41ca9c0cdbd704580eb3a9ccf07b9b576094d7b86a012baebc95681999dd38f4f444afd28504cb3a89f2ef16b31d4ab61a0739025a + languageName: node + linkType: hard + +"type-detect@npm:4.0.8, type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 + languageName: node + linkType: hard + +"type-fest@npm:^0.20.2": + version: 0.20.2 + resolution: "type-fest@npm:0.20.2" + checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 + languageName: node + linkType: hard + +"type-fest@npm:^0.21.3": + version: 0.21.3 + resolution: "type-fest@npm:0.21.3" + checksum: e6b32a3b3877f04339bae01c193b273c62ba7bfc9e325b8703c4ee1b32dc8fe4ef5dfa54bf78265e069f7667d058e360ae0f37be5af9f153b22382cd55a9afe0 + languageName: node + linkType: hard + +"type-fest@npm:^0.7.1": + version: 0.7.1 + resolution: "type-fest@npm:0.7.1" + checksum: 5b1b113529d59949d97b76977d545989ddc11b81bb0c766b6d2ccc65473cb4b4a5c7d24f5be2c2bb2de302a5d7a13c1732ea1d34c8c59b7e0ec1f890cf7fc424 + languageName: node + linkType: hard + +"type-fest@npm:^1.0.1": + version: 1.4.0 + resolution: "type-fest@npm:1.4.0" + checksum: b011c3388665b097ae6a109a437a04d6f61d81b7357f74cbcb02246f2f5bd72b888ae33631b99871388122ba0a87f4ff1c94078e7119ff22c70e52c0ff828201 + languageName: node + linkType: hard + +"type-fest@npm:^2.13.0, type-fest@npm:^2.5.0": + version: 2.19.0 + resolution: "type-fest@npm:2.19.0" + checksum: a4ef07ece297c9fba78fc1bd6d85dff4472fe043ede98bd4710d2615d15776902b595abf62bd78339ed6278f021235fb28a96361f8be86ed754f778973a0d278 + languageName: node + linkType: hard + +"type-is@npm:^1.6.16, type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: 0.3.0 + mime-types: ~2.1.24 + checksum: 2c8e47675d55f8b4e404bcf529abdf5036c537a04c2b20177bcf78c9e3c1da69da3942b1346e6edb09e823228c0ee656ef0e033765ec39a70d496ef601a0c657 + languageName: node + linkType: hard + +"typedarray-to-buffer@npm:^3.1.5": + version: 3.1.5 + resolution: "typedarray-to-buffer@npm:3.1.5" + dependencies: + is-typedarray: ^1.0.0 + checksum: 99c11aaa8f45189fcfba6b8a4825fd684a321caa9bd7a76a27cf0c7732c174d198b99f449c52c3818107430b5f41c0ccbbfb75cb2ee3ca4a9451710986d61a60 + languageName: node + linkType: hard + +"typedarray-to-buffer@npm:~1.0.0": + version: 1.0.4 + resolution: "typedarray-to-buffer@npm:1.0.4" + checksum: ac6989c456a0b175c8362b3ebbd8a74af7b9bcc94f9dc9ffd34436569cd29aea6a1e0e5f5752d0d5bd855a55b2520e960d1d4cb9c9149f863ce09220540df17f + languageName: node + linkType: hard + +"typedarray@npm:^0.0.6": + version: 0.0.6 + resolution: "typedarray@npm:0.0.6" + checksum: 33b39f3d0e8463985eeaeeacc3cb2e28bc3dfaf2a5ed219628c0b629d5d7b810b0eb2165f9f607c34871d5daa92ba1dc69f49051cf7d578b4cbd26c340b9d1b1 + languageName: node + linkType: hard + +"typedoc-plugin-frontmatter@npm:^0.0.2": + version: 0.0.2 + resolution: "typedoc-plugin-frontmatter@npm:0.0.2" + dependencies: + yaml: ^2.2.2 + checksum: 44cbdb82e3fd8f4eb89cdf54783b5b07b03a57edc7bda85a48280edba73f401a2f5439cbba97426dd79e9584c410244af5dd20d5d7281c27d67d61675fa7aaef + languageName: node + linkType: hard + +"typedoc-plugin-markdown@npm:4.0.0-next.25": + version: 4.0.0-next.25 + resolution: "typedoc-plugin-markdown@npm:4.0.0-next.25" + peerDependencies: + typedoc: ">=0.25.0" + checksum: 284e2ce44446faf8db5fc54dfa84e7cd819cfc60bbed12ffb781cb24a166ba6b3a220c542990a3eb14aefff33f1d7c8322378297551f55476155cf532fbbb807 + languageName: node + linkType: hard + +"typedoc-plugin-merge-modules@npm:^5.1.0": + version: 5.1.0 + resolution: "typedoc-plugin-merge-modules@npm:5.1.0" + peerDependencies: + typedoc: 0.24.x || 0.25.x + checksum: f01d825a1c6b73c29faaf515e76076931b16bcc5762c8e9b56d18a7eca6d450bd3691012e96bc3a09ce05f29aef90744e93e187171c561ef0a3c2c1fe116803f + languageName: node + linkType: hard + +"typedoc@npm:^0.25.0": + version: 0.25.4 + resolution: "typedoc@npm:0.25.4" + dependencies: + lunr: ^2.3.9 + marked: ^4.3.0 + minimatch: ^9.0.3 + shiki: ^0.14.1 + peerDependencies: + typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x + bin: + typedoc: bin/typedoc + checksum: 6d441baa277c0db4d577db2932a7af316d175415841e2faf2e68e3eda6ad60356c54f56374f89c5233d7bd5c057b0337455e5d484d8463e1445e67c37a6d94eb + languageName: node + linkType: hard + +"typescript@npm:^5.4.2": + version: 5.4.2 + resolution: "typescript@npm:5.4.2" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 96d80fde25a09bcb04d399082fb27a808a9e17c2111e43849d2aafbd642d835e4f4ef0de09b0ba795ec2a700be6c4c2c3f62bf4660c05404c948727b5bbfb32a + languageName: node + linkType: hard + +"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: c1b669146bca5529873aae60870e243fa8140c85f57ca32c42f898f586d73ce4a6b4f6bb02ae312729e214d7f5859a0c70da3e527a116fdf5ad00c9fc733ecc6 + languageName: node + linkType: hard + +"typical@npm:^4.0.0": + version: 4.0.0 + resolution: "typical@npm:4.0.0" + checksum: a242081956825328f535e6195a924240b34daf6e7fdb573a1809a42b9f37fb8114fa99c7ab89a695e0cdb419d4149d067f6723e4b95855ffd39c6c4ca378efb3 + languageName: node + linkType: hard + +"typical@npm:^5.2.0": + version: 5.2.0 + resolution: "typical@npm:5.2.0" + checksum: ccaeb151a9a556291b495571ca44c4660f736fb49c29314bbf773c90fad92e9485d3cc2b074c933866c1595abbbc962f2b8bfc6e0f52a8c6b0cdd205442036ac + languageName: node + linkType: hard + +"typical@npm:^7.1.1": + version: 7.1.1 + resolution: "typical@npm:7.1.1" + checksum: 292c64a2e3d2296fd1b7a92bbe3a9ad683f643f3faa8c9b45f6911105da54246817a3e2a4f0fdd01bb4c49d2b940618ad30b6771ac1c94bf690a40c706f657fa + languageName: node + linkType: hard + +"ua-parser-js@npm:^1.0.33": + version: 1.0.37 + resolution: "ua-parser-js@npm:1.0.37" + checksum: 4d481c720d523366d7762dc8a46a1b58967d979aacf786f9ceceb1cd767de069f64a4bdffb63956294f1c0696eb465ddb950f28ba90571709e33521b4bd75e07 + languageName: node + linkType: hard + +"unbzip2-stream@npm:1.4.3": + version: 1.4.3 + resolution: "unbzip2-stream@npm:1.4.3" + dependencies: + buffer: ^5.2.1 + through: ^2.3.8 + checksum: 0e67c4a91f4fa0fc7b4045f8b914d3498c2fc2e8c39c359977708ec85ac6d6029840e97f508675fdbdf21fcb8d276ca502043406f3682b70f075e69aae626d1d + languageName: node + linkType: hard + +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 + languageName: node + linkType: hard + +"undici@npm:^5.14.0": + version: 5.28.2 + resolution: "undici@npm:5.28.2" + dependencies: + "@fastify/busboy": ^2.0.0 + checksum: f9e9335803f962fff07c3c11c6d50bbc76248bacf97035047155adb29c3622a65bd6bff23a22218189740133149d22e63b68131d8c40e78ac6cb4b6d686a6dfa + languageName: node + linkType: hard + +"unherit@npm:^1.0.4": + version: 1.1.3 + resolution: "unherit@npm:1.1.3" + dependencies: + inherits: ^2.0.0 + xtend: ^4.0.0 + checksum: fd7922f84fc0bfb7c4df6d1f5a50b5b94a0218e3cda98a54dbbd209226ddd4072d742d3df44d0e295ab08d5ccfd304a1e193dfe31a86d2a91b7cb9fdac093194 + languageName: node + linkType: hard + +"unicode-canonical-property-names-ecmascript@npm:^2.0.0": + version: 2.0.0 + resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" + checksum: 39be078afd014c14dcd957a7a46a60061bc37c4508ba146517f85f60361acf4c7539552645ece25de840e17e293baa5556268d091ca6762747fdd0c705001a45 + languageName: node + linkType: hard + +"unicode-emoji-modifier-base@npm:^1.0.0": + version: 1.0.0 + resolution: "unicode-emoji-modifier-base@npm:1.0.0" + checksum: 6e1521d35fa69493207eb8b41f8edb95985d8b3faf07c01d820a1830b5e8403e20002563e2f84683e8e962a49beccae789f0879356bf92a4ec7a4dd8e2d16fdb + languageName: node + linkType: hard + +"unicode-match-property-ecmascript@npm:^2.0.0": + version: 2.0.0 + resolution: "unicode-match-property-ecmascript@npm:2.0.0" + dependencies: + unicode-canonical-property-names-ecmascript: ^2.0.0 + unicode-property-aliases-ecmascript: ^2.0.0 + checksum: 1f34a7434a23df4885b5890ac36c5b2161a809887000be560f56ad4b11126d433c0c1c39baf1016bdabed4ec54829a6190ee37aa24919aa116dc1a5a8a62965a + languageName: node + linkType: hard + +"unicode-match-property-value-ecmascript@npm:^2.1.0": + version: 2.1.0 + resolution: "unicode-match-property-value-ecmascript@npm:2.1.0" + checksum: 8d6f5f586b9ce1ed0e84a37df6b42fdba1317a05b5df0c249962bd5da89528771e2d149837cad11aa26bcb84c35355cb9f58a10c3d41fa3b899181ece6c85220 + languageName: node + linkType: hard + +"unicode-property-aliases-ecmascript@npm:^2.0.0": + version: 2.1.0 + resolution: "unicode-property-aliases-ecmascript@npm:2.1.0" + checksum: 243524431893649b62cc674d877bd64ef292d6071dd2fd01ab4d5ad26efbc104ffcd064f93f8a06b7e4ec54c172bf03f6417921a0d8c3a9994161fe1f88f815b + languageName: node + linkType: hard + +"unicorn-magic@npm:^0.1.0": + version: 0.1.0 + resolution: "unicorn-magic@npm:0.1.0" + checksum: 48c5882ca3378f380318c0b4eb1d73b7e3c5b728859b060276e0a490051d4180966beeb48962d850fd0c6816543bcdfc28629dcd030bb62a286a2ae2acb5acb6 + languageName: node + linkType: hard + +"unified@npm:9.2.0": + version: 9.2.0 + resolution: "unified@npm:9.2.0" + dependencies: + bail: ^1.0.0 + extend: ^3.0.0 + is-buffer: ^2.0.0 + is-plain-obj: ^2.0.0 + trough: ^1.0.0 + vfile: ^4.0.0 + checksum: 0cac4ae119893fbd49d309b4db48595e4d4e9f0a2dc1dde4d0074059f9a46012a2905f37c1346715e583f30c970bc8078db8462675411d39ff5036ae18b4fb8a + languageName: node + linkType: hard + +"unified@npm:^11.0.0, unified@npm:^11.0.3, unified@npm:^11.0.4": + version: 11.0.4 + resolution: "unified@npm:11.0.4" + dependencies: + "@types/unist": ^3.0.0 + bail: ^2.0.0 + devlop: ^1.0.0 + extend: ^3.0.0 + is-plain-obj: ^4.0.0 + trough: ^2.0.0 + vfile: ^6.0.0 + checksum: cfb023913480ac2bd5e787ffb8c27782c43e6be4a55f8f1c288233fce46a7ebe7718ccc5adb80bf8d56b7ef85f5fc32239c7bfccda006f9f2382e0cc2e2a77e4 + languageName: node + linkType: hard + +"unified@npm:^9.2.2": + version: 9.2.2 + resolution: "unified@npm:9.2.2" + dependencies: + bail: ^1.0.0 + extend: ^3.0.0 + is-buffer: ^2.0.0 + is-plain-obj: ^2.0.0 + trough: ^1.0.0 + vfile: ^4.0.0 + checksum: 7c24461be7de4145939739ce50d18227c5fbdf9b3bc5a29dabb1ce26dd3e8bd4a1c385865f6f825f3b49230953ee8b591f23beab3bb3643e3e9dc37aa8a089d5 + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: ^4.0.0 + checksum: 8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: ^0.1.4 + checksum: 0884b58365af59f89739e6f71e3feacb5b1b41f2df2d842d0757933620e6de08eff347d27e9d499b43c40476cbaf7988638d3acb2ffbcb9d35fd035591adfd15 + languageName: node + linkType: hard + +"unique-string@npm:^2.0.0": + version: 2.0.0 + resolution: "unique-string@npm:2.0.0" + dependencies: + crypto-random-string: ^2.0.0 + checksum: ef68f639136bcfe040cf7e3cd7a8dff076a665288122855148a6f7134092e6ed33bf83a7f3a9185e46c98dddc445a0da6ac25612afa1a7c38b8b654d6c02498e + languageName: node + linkType: hard + +"unique-string@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-string@npm:3.0.0" + dependencies: + crypto-random-string: ^4.0.0 + checksum: 1a1e2e7d02eab1bb10f720475da735e1990c8a5ff34edd1a3b6bc31590cb4210b7a1233d779360cc622ce11c211e43afa1628dd658f35d3e6a89964b622940df + languageName: node + linkType: hard + +"unist-builder@npm:2.0.3, unist-builder@npm:^2.0.0": + version: 2.0.3 + resolution: "unist-builder@npm:2.0.3" + checksum: e946fdf77dbfc320feaece137ce4959ae2da6614abd1623bd39512dc741a9d5f313eb2ba79f8887d941365dccddec7fef4e953827475e392bf49b45336f597f6 + languageName: node + linkType: hard + +"unist-util-find-after@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-find-after@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + checksum: e64bd5ebee7ac021cf990bf33e9ec29fc6452159187d4a7fa0f77334bea8e378fea7a7fb0bcf957300b2ffdba902ff25b62c165fc8b86309613da35ad793ada0 + languageName: node + linkType: hard + +"unist-util-generated@npm:^1.0.0": + version: 1.1.6 + resolution: "unist-util-generated@npm:1.1.6" + checksum: 86239ff88a08800d52198f2f0e15911f05bab2dad17cef95550f7c2728f15ebb0344694fcc3101d05762d88adaf86cb85aa7a3300fedabd0b6d7d00b41cdcb7f + languageName: node + linkType: hard + +"unist-util-is@npm:^4.0.0": + version: 4.1.0 + resolution: "unist-util-is@npm:4.1.0" + checksum: 726484cd2adc9be75a939aeedd48720f88294899c2e4a3143da413ae593f2b28037570730d5cf5fd910ff41f3bc1501e3d636b6814c478d71126581ef695f7ea + languageName: node + linkType: hard + +"unist-util-is@npm:^6.0.0": + version: 6.0.0 + resolution: "unist-util-is@npm:6.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: f630a925126594af9993b091cf807b86811371e465b5049a6283e08537d3e6ba0f7e248e1e7dab52cfe33f9002606acef093441137181b327f6fe504884b20e2 + languageName: node + linkType: hard + +"unist-util-position-from-estree@npm:^2.0.0": + version: 2.0.0 + resolution: "unist-util-position-from-estree@npm:2.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: d3b3048a5727c2367f64ef6dcc5b20c4717215ef8b1372ff9a7c426297c5d1e5776409938acd01531213e2cd2543218d16e73f9f862f318e9496e2c73bb18354 + languageName: node + linkType: hard + +"unist-util-position@npm:^3.0.0": + version: 3.1.0 + resolution: "unist-util-position@npm:3.1.0" + checksum: 10b3952e32a1ffabbecad41c3946237f7059f5bb6436796da05531a285f50b97e4f37cfc2f7164676d041063f40fe1ad92fbb8ca38d3ae8747328ebe738d738f + languageName: node + linkType: hard + +"unist-util-position@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-position@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: f89b27989b19f07878de9579cd8db2aa0194c8360db69e2c99bd2124a480d79c08f04b73a64daf01a8fb3af7cba65ff4b45a0b978ca243226084ad5f5d441dde + languageName: node + linkType: hard + +"unist-util-remove-position@npm:^2.0.0": + version: 2.0.1 + resolution: "unist-util-remove-position@npm:2.0.1" + dependencies: + unist-util-visit: ^2.0.0 + checksum: 4149294969f1a78a367b5d03eb0a138aa8320a39e1b15686647a2bec5945af3df27f2936a1e9752ecbb4a82dc23bd86f7e5a0ee048e5eeaedc2deb9237872795 + languageName: node + linkType: hard + +"unist-util-remove-position@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-remove-position@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + unist-util-visit: ^5.0.0 + checksum: 8aabdb9d0e3e744141bc123d8f87b90835d521209ad3c6c4619d403b324537152f0b8f20dda839b40c3aa0abfbf1828b3635a7a8bb159c3ed469e743023510ee + languageName: node + linkType: hard + +"unist-util-remove@npm:^2.0.0": + version: 2.1.0 + resolution: "unist-util-remove@npm:2.1.0" + dependencies: + unist-util-is: ^4.0.0 + checksum: 99e54f3ea0523f8cf957579a6e84e5b58427bffab929cc7f6aa5119581f929db683dd4691ea5483df0c272f486dda9dbd04f4ab74dca6cae1f3ebe8e4261a4d9 + languageName: node + linkType: hard + +"unist-util-stringify-position@npm:^2.0.0": + version: 2.0.3 + resolution: "unist-util-stringify-position@npm:2.0.3" + dependencies: + "@types/unist": ^2.0.2 + checksum: f755cadc959f9074fe999578a1a242761296705a7fe87f333a37c00044de74ab4b184b3812989a57d4cd12211f0b14ad397b327c3a594c7af84361b1c25a7f09 + languageName: node + linkType: hard + +"unist-util-stringify-position@npm:^4.0.0": + version: 4.0.0 + resolution: "unist-util-stringify-position@npm:4.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: e2e7aee4b92ddb64d314b4ac89eef7a46e4c829cbd3ee4aee516d100772b490eb6b4974f653ba0717a0071ca6ea0770bf22b0a2ea62c65fcba1d071285e96324 + languageName: node + linkType: hard + +"unist-util-visit-parents@npm:^3.0.0": + version: 3.1.1 + resolution: "unist-util-visit-parents@npm:3.1.1" + dependencies: + "@types/unist": ^2.0.0 + unist-util-is: ^4.0.0 + checksum: 1170e397dff88fab01e76d5154981666eb0291019d2462cff7a2961a3e76d3533b42eaa16b5b7e2d41ad42a5ea7d112301458283d255993e660511387bf67bc3 + languageName: node + linkType: hard + +"unist-util-visit-parents@npm:^6.0.0": + version: 6.0.1 + resolution: "unist-util-visit-parents@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + checksum: 08927647c579f63b91aafcbec9966dc4a7d0af1e5e26fc69f4e3e6a01215084835a2321b06f3cbe7bf7914a852830fc1439f0fc3d7153d8804ac3ef851ddfa20 + languageName: node + linkType: hard + +"unist-util-visit@npm:2.0.3, unist-util-visit@npm:^2.0.0, unist-util-visit@npm:^2.0.3": + version: 2.0.3 + resolution: "unist-util-visit@npm:2.0.3" + dependencies: + "@types/unist": ^2.0.0 + unist-util-is: ^4.0.0 + unist-util-visit-parents: ^3.0.0 + checksum: 1fe19d500e212128f96d8c3cfa3312846e586b797748a1fd195fe6479f06bc90a6f6904deb08eefc00dd58e83a1c8a32fb8677252d2273ad7a5e624525b69b8f + languageName: node + linkType: hard + +"unist-util-visit@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-visit@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 9ec42e618e7e5d0202f3c191cd30791b51641285732767ee2e6bcd035931032e3c1b29093f4d7fd0c79175bbc1f26f24f26ee49770d32be76f8730a652a857e6 + languageName: node + linkType: hard + +"universalify@npm:^0.1.0": + version: 0.1.2 + resolution: "universalify@npm:0.1.2" + checksum: 40cdc60f6e61070fe658ca36016a8f4ec216b29bf04a55dce14e3710cc84c7448538ef4dad3728d0bfe29975ccd7bfb5f414c45e7b78883567fb31b246f02dff + languageName: node + linkType: hard + +"universalify@npm:^2.0.0": + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: ecd8469fe0db28e7de9e5289d32bd1b6ba8f7183db34f3bfc4ca53c49891c2d6aa05f3fb3936a81285a905cc509fb641a0c3fc131ec786167eff41236ae32e60 + languageName: node + linkType: hard + +"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 + languageName: node + linkType: hard + +"unzipit@npm:^1.4.3": + version: 1.4.3 + resolution: "unzipit@npm:1.4.3" + dependencies: + uzip-module: ^1.0.2 + checksum: ce29348edab7b5fb5b7b4d43437f48e35812ac8b3cc2d76efd1acfcad6dd1b96b4f96bfd03250a724b87ba99dd531d7727ad24b590acf727dde79f54f5e779ed + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.0.13": + version: 1.0.13 + resolution: "update-browserslist-db@npm:1.0.13" + dependencies: + escalade: ^3.1.1 + picocolors: ^1.0.0 + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 1e47d80182ab6e4ad35396ad8b61008ae2a1330221175d0abd37689658bdb61af9b705bfc41057fd16682474d79944fb2d86767c5ed5ae34b6276b9bed353322 + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.1.0": + version: 1.1.1 + resolution: "update-browserslist-db@npm:1.1.1" + dependencies: + escalade: ^3.2.0 + picocolors: ^1.1.0 + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 2ea11bd2562122162c3e438d83a1f9125238c0844b6d16d366e3276d0c0acac6036822dc7df65fc5a89c699cdf9f174acf439c39bedf3f9a2f3983976e4b4c3e + languageName: node + linkType: hard + +"update-check@npm:1.5.4": + version: 1.5.4 + resolution: "update-check@npm:1.5.4" + dependencies: + registry-auth-token: 3.3.2 + registry-url: 3.1.0 + checksum: 2c9f7de6f030364c5ea02a341e5ae2dfe76da6559b32d40dd3b047b3ac0927408cf92d322c51cd8e009688210a85ccbf1eba449762a65a0d1b14f3cdf1ea5c48 + languageName: node + linkType: hard + +"update-notifier@npm:^5.1.0": + version: 5.1.0 + resolution: "update-notifier@npm:5.1.0" + dependencies: + boxen: ^5.0.0 + chalk: ^4.1.0 + configstore: ^5.0.1 + has-yarn: ^2.1.0 + import-lazy: ^2.1.0 + is-ci: ^2.0.0 + is-installed-globally: ^0.4.0 + is-npm: ^5.0.0 + is-yarn-global: ^0.3.0 + latest-version: ^5.1.0 + pupa: ^2.1.1 + semver: ^7.3.4 + semver-diff: ^3.1.1 + xdg-basedir: ^4.0.0 + checksum: 461e5e5b002419296d3868ee2abe0f9ab3e1846d9db642936d0c46f838872ec56069eddfe662c45ce1af0a8d6d5026353728de2e0a95ab2e3546a22ea077caf1 + languageName: node + linkType: hard + +"update-notifier@npm:^6.0.2": + version: 6.0.2 + resolution: "update-notifier@npm:6.0.2" + dependencies: + boxen: ^7.0.0 + chalk: ^5.0.1 + configstore: ^6.0.0 + has-yarn: ^3.0.0 + import-lazy: ^4.0.0 + is-ci: ^3.0.1 + is-installed-globally: ^0.4.0 + is-npm: ^6.0.0 + is-yarn-global: ^0.4.0 + latest-version: ^7.0.0 + pupa: ^3.1.0 + semver: ^7.3.7 + semver-diff: ^4.0.0 + xdg-basedir: ^5.1.0 + checksum: 4bae7b3eca7b2068b6b87dde88c9dad24831fa913a5b83ecb39a7e4702c93e8b05fd9bcac5f1a005178f6e5dc859e0b3817ddda833d2a7ab92c6485e078b3cc8 + languageName: node + linkType: hard + +"uri-js@npm:^4.2.2": + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" + dependencies: + punycode: ^2.1.0 + checksum: 7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 + languageName: node + linkType: hard + +"url-loader@npm:^4.1.1": + version: 4.1.1 + resolution: "url-loader@npm:4.1.1" + dependencies: + loader-utils: ^2.0.0 + mime-types: ^2.1.27 + schema-utils: ^3.0.0 + peerDependencies: + file-loader: "*" + webpack: ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + file-loader: + optional: true + checksum: c1122a992c6cff70a7e56dfc2b7474534d48eb40b2cc75467cde0c6972e7597faf8e43acb4f45f93c2473645dfd803bcbc20960b57544dd1e4c96e77f72ba6fd + languageName: node + linkType: hard + +"url-parse-lax@npm:^3.0.0": + version: 3.0.0 + resolution: "url-parse-lax@npm:3.0.0" + dependencies: + prepend-http: ^2.0.0 + checksum: 1040e357750451173132228036aff1fd04abbd43eac1fb3e4fca7495a078bcb8d33cb765fe71ad7e473d9c94d98fd67adca63bd2716c815a2da066198dd37217 + languageName: node + linkType: hard + +"url@npm:^0.11.3": + version: 0.11.3 + resolution: "url@npm:0.11.3" + dependencies: + punycode: ^1.4.1 + qs: ^6.11.2 + checksum: f9e7886f46a16f96d2e42fbcc5d682c231c55ef5442c1ff66150c0f6556f6e3a97d094a84f51be15ec2432711d212eb60426659ce418f5fcadeaa3f601532c4e + 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" + checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 + languageName: node + linkType: hard + +"util@npm:^0.12.5": + version: 0.12.5 + resolution: "util@npm:0.12.5" + dependencies: + inherits: ^2.0.3 + is-arguments: ^1.0.4 + is-generator-function: ^1.0.7 + is-typed-array: ^1.1.3 + which-typed-array: ^1.1.2 + checksum: 705e51f0de5b446f4edec10739752ac25856541e0254ea1e7e45e5b9f9b0cb105bc4bd415736a6210edc68245a7f903bf085ffb08dd7deb8a0e847f60538a38a + languageName: node + linkType: hard + +"utila@npm:~0.4": + version: 0.4.0 + resolution: "utila@npm:0.4.0" + checksum: 97ffd3bd2bb80c773429d3fb8396469115cd190dded1e733f190d8b602bd0a1bcd6216b7ce3c4395ee3c79e3c879c19d268dbaae3093564cb169ad1212d436f4 + languageName: node + linkType: hard + +"utility-types@npm:^3.10.0": + version: 3.10.0 + resolution: "utility-types@npm:3.10.0" + checksum: 8f274415c6196ab62883b8bd98c9d2f8829b58016e4269aaa1ebd84184ac5dda7dc2ca45800c0d5e0e0650966ba063bf9a412aaeaea6850ca4440a391283d5c8 + languageName: node + linkType: hard + +"utils-merge@npm:1.0.1": + version: 1.0.1 + resolution: "utils-merge@npm:1.0.1" + checksum: c81095493225ecfc28add49c106ca4f09cdf56bc66731aa8dabc2edbbccb1e1bfe2de6a115e5c6a380d3ea166d1636410b62ef216bb07b3feb1cfde1d95d5080 + languageName: node + linkType: hard + +"uuid@npm:^8.3.2": + version: 8.3.2 + resolution: "uuid@npm:8.3.2" + bin: + uuid: dist/bin/uuid + checksum: 5575a8a75c13120e2f10e6ddc801b2c7ed7d8f3c8ac22c7ed0c7b2ba6383ec0abda88c905085d630e251719e0777045ae3236f04c812184b7c765f63a70e58df + languageName: node + linkType: hard + +"uzip-module@npm:^1.0.2": + version: 1.0.3 + resolution: "uzip-module@npm:1.0.3" + checksum: fc286c44a04d75055577fae8293d3fee499d1e850f87e88c158b1e3657f4794a3a40ca2d34f73474ff82917176dd5ca9d1c0d1e375a083714e11afabd3afa423 + languageName: node + linkType: hard + +"v8-compile-cache-lib@npm:^3.0.1": + version: 3.0.1 + resolution: "v8-compile-cache-lib@npm:3.0.1" + checksum: 78089ad549e21bcdbfca10c08850022b22024cdcc2da9b168bcf5a73a6ed7bf01a9cebb9eac28e03cd23a684d81e0502797e88f3ccd27a32aeab1cfc44c39da0 + languageName: node + linkType: hard + +"v8-to-istanbul@npm:^9.0.1": + version: 9.2.0 + resolution: "v8-to-istanbul@npm:9.2.0" + dependencies: + "@jridgewell/trace-mapping": ^0.3.12 + "@types/istanbul-lib-coverage": ^2.0.1 + convert-source-map: ^2.0.0 + checksum: 31ef98c6a31b1dab6be024cf914f235408cd4c0dc56a5c744a5eea1a9e019ba279e1b6f90d695b78c3186feed391ed492380ccf095009e2eb91f3d058f0b4491 + languageName: node + linkType: hard + +"value-equal@npm:^1.0.1": + version: 1.0.1 + resolution: "value-equal@npm:1.0.1" + checksum: bb7ae1facc76b5cf8071aeb6c13d284d023fdb370478d10a5d64508e0e6e53bb459c4bbe34258df29d82e6f561f874f0105eba38de0e61fe9edd0bdce07a77a2 + languageName: node + linkType: hard + +"vary@npm:^1.1.2, vary@npm:~1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: ae0123222c6df65b437669d63dfa8c36cee20a504101b2fcd97b8bf76f91259c17f9f2b4d70a1e3c6bbcee7f51b28392833adb6b2770b23b01abec84e369660b + languageName: node + linkType: hard + +"vfile-location@npm:^3.0.0, vfile-location@npm:^3.2.0": + version: 3.2.0 + resolution: "vfile-location@npm:3.2.0" + checksum: 9bb3df6d0be31b5dd2d8da0170c27b7045c64493a8ba7b6ff7af8596c524fc8896924b8dd85ae12d201eead2709217a0fbc44927b7264f4bbf0aa8027a78be9c + languageName: node + linkType: hard + +"vfile-location@npm:^5.0.0": + version: 5.0.2 + resolution: "vfile-location@npm:5.0.2" + dependencies: + "@types/unist": ^3.0.0 + vfile: ^6.0.0 + checksum: b61c048cedad3555b4f007f390412c6503f58a6a130b58badf4ee340c87e0d7421e9c86bbc1494c57dedfccadb60f5176cc60ba3098209d99fb3a3d8804e4c38 + languageName: node + linkType: hard + +"vfile-message@npm:^2.0.0": + version: 2.0.4 + resolution: "vfile-message@npm:2.0.4" + dependencies: + "@types/unist": ^2.0.0 + unist-util-stringify-position: ^2.0.0 + checksum: 1bade499790f46ca5aba04bdce07a1e37c2636a8872e05cf32c26becc912826710b7eb063d30c5754fdfaeedc8a7658e78df10b3bc535c844890ec8a184f5643 + languageName: node + linkType: hard + +"vfile-message@npm:^4.0.0": + version: 4.0.2 + resolution: "vfile-message@npm:4.0.2" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 964e7e119f4c0e0270fc269119c41c96da20afa01acb7c9809a88365c8e0c64aa692fafbd952669382b978002ecd7ad31ef4446d85e8a22cdb62f6df20186c2d + languageName: node + linkType: hard + +"vfile@npm:^4.0.0": + version: 4.2.1 + resolution: "vfile@npm:4.2.1" + dependencies: + "@types/unist": ^2.0.0 + is-buffer: ^2.0.0 + unist-util-stringify-position: ^2.0.0 + vfile-message: ^2.0.0 + checksum: ee5726e10d170472cde778fc22e0f7499caa096eb85babea5d0ce0941455b721037ee1c9e6ae506ca2803250acd313d0f464328ead0b55cfe7cb6315f1b462d6 + languageName: node + linkType: hard + +"vfile@npm:^6.0.0, vfile@npm:^6.0.1": + version: 6.0.1 + resolution: "vfile@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + vfile-message: ^4.0.0 + checksum: 05ccee73aeb00402bc8a5d0708af299e9f4a33f5132805449099295085e3ca3b0d018328bad9ff44cf2e6f4cd364f1d558d3fb9b394243a25b2739207edcb0ed + languageName: node + linkType: hard + +"vscode-languageserver-textdocument@npm:^1.0.11": + version: 1.0.11 + resolution: "vscode-languageserver-textdocument@npm:1.0.11" + checksum: ea7cdc9d4ffaae5952071fa11d17d714215a76444e6936c9359f94b9ba3222a52a55edb5bd5928bd3e9712b900a9f175bb3565ec1c8923234fe3bd327584bafb + languageName: node + linkType: hard + +"vscode-oniguruma@npm:^1.7.0": + version: 1.7.0 + resolution: "vscode-oniguruma@npm:1.7.0" + checksum: 53519d91d90593e6fb080260892e87d447e9b200c4964d766772b5053f5699066539d92100f77f1302c91e8fc5d9c772fbe40fe4c90f3d411a96d5a9b1e63f42 + languageName: node + linkType: hard + +"vscode-textmate@npm:^8.0.0": + version: 8.0.0 + resolution: "vscode-textmate@npm:8.0.0" + checksum: 127780dfea89559d70b8326df6ec344cfd701312dd7f3f591a718693812b7852c30b6715e3cfc8b3200a4e2515b4c96f0843c0eacc0a3020969b5de262c2a4bb + languageName: node + linkType: hard + +"vscode-uri@npm:^3.0.8": + version: 3.0.8 + resolution: "vscode-uri@npm:3.0.8" + checksum: 514249126850c0a41a7d8c3c2836cab35983b9dc1938b903cfa253b9e33974c1416d62a00111385adcfa2b98df456437ab704f709a2ecca76a90134ef5eb4832 + languageName: node + linkType: hard + +"wait-on@npm:^6.0.1": + version: 6.0.1 + resolution: "wait-on@npm:6.0.1" + dependencies: + axios: ^0.25.0 + joi: ^17.6.0 + lodash: ^4.17.21 + minimist: ^1.2.5 + rxjs: ^7.5.4 + bin: + wait-on: bin/wait-on + checksum: e4d62aa4145d99fe34747ccf7506d4b4d6e60dd677c0eb18a51e316d38116ace2d194e4b22a9eb7b767b0282f39878ddcc4ae9440dcb0c005c9150668747cf5b + languageName: node + linkType: hard + +"watchpack@npm:^2.1.1, watchpack@npm:^2.4.0": + version: 2.4.0 + resolution: "watchpack@npm:2.4.0" + dependencies: + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.1.2 + checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131 + languageName: node + linkType: hard + +"wbuf@npm:^1.1.0, wbuf@npm:^1.7.3": + version: 1.7.3 + resolution: "wbuf@npm:1.7.3" + dependencies: + minimalistic-assert: ^1.0.0 + checksum: 2abc306c96930b757972a1c4650eb6b25b5d99f24088714957f88629e137db569368c5de0e57986c89ea70db2f1df9bba11a87cb6d0c8694b6f53a0159fab3bf + languageName: node + linkType: hard + +"web-namespaces@npm:^1.0.0": + version: 1.1.4 + resolution: "web-namespaces@npm:1.1.4" + checksum: 5149842ccbfbc56fe4f8758957b3f8c8616a281874a5bb84aa1b305e4436a9bad853d21c629a7b8f174902449e1489c7a6c724fccf60965077c5636bd8aed42b + languageName: node + linkType: hard + +"web-namespaces@npm:^2.0.0": + version: 2.0.1 + resolution: "web-namespaces@npm:2.0.1" + checksum: b6d9f02f1a43d0ef0848a812d89c83801d5bbad57d8bb61f02eb6d7eb794c3736f6cc2e1191664bb26136594c8218ac609f4069722c6f56d9fc2d808fa9271c6 + languageName: node + linkType: hard + +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: c92a0a6ab95314bde9c32e1d0a6dfac83b578f8fa5f21e675bc2706ed6981bc26b7eb7e6a1fab158e5ce4adf9caa4a0aee49a52505d4d13c7be545f15021b17c + languageName: node + linkType: hard + +"webidl-conversions@npm:^7.0.0": + version: 7.0.0 + resolution: "webidl-conversions@npm:7.0.0" + checksum: f05588567a2a76428515333eff87200fae6c83c3948a7482ebb109562971e77ef6dc49749afa58abb993391227c5697b3ecca52018793e0cb4620a48f10bd21b + languageName: node + linkType: hard + +"webpack-bundle-analyzer@npm:^4.5.0, webpack-bundle-analyzer@npm:^4.9.0": + version: 4.10.1 + resolution: "webpack-bundle-analyzer@npm:4.10.1" + dependencies: + "@discoveryjs/json-ext": 0.5.7 + acorn: ^8.0.4 + acorn-walk: ^8.0.0 + commander: ^7.2.0 + debounce: ^1.2.1 + escape-string-regexp: ^4.0.0 + gzip-size: ^6.0.0 + html-escaper: ^2.0.2 + is-plain-object: ^5.0.0 + opener: ^1.5.2 + picocolors: ^1.0.0 + sirv: ^2.0.3 + ws: ^7.3.1 + bin: + webpack-bundle-analyzer: lib/bin/analyzer.js + checksum: 77f48f10a493b1cc95674526472978a2de32412ddbf556bd3903738f14890611426f19477352993efe5a9fd6ca16711eb912d986f2221b17ba6eeca1b6f71fb6 + languageName: node + linkType: hard + +"webpack-cli@npm:^5.1.4": + version: 5.1.4 + resolution: "webpack-cli@npm:5.1.4" + dependencies: + "@discoveryjs/json-ext": ^0.5.0 + "@webpack-cli/configtest": ^2.1.1 + "@webpack-cli/info": ^2.0.2 + "@webpack-cli/serve": ^2.0.5 + colorette: ^2.0.14 + commander: ^10.0.1 + cross-spawn: ^7.0.3 + envinfo: ^7.7.3 + fastest-levenshtein: ^1.0.12 + import-local: ^3.0.2 + interpret: ^3.1.1 + rechoir: ^0.8.0 + webpack-merge: ^5.7.3 + peerDependencies: + webpack: 5.x.x + peerDependenciesMeta: + "@webpack-cli/generators": + optional: true + webpack-bundle-analyzer: + optional: true + webpack-dev-server: + optional: true + bin: + webpack-cli: bin/cli.js + checksum: 3a4ad0d0342a6815c850ee4633cc2a8a5dae04f918e7847f180bf24ab400803cf8a8943707ffbed03eb20fe6ce647f996f60a2aade87b0b4a9954da3da172ce0 + languageName: node + linkType: hard + +"webpack-dev-middleware@npm:^5.3.1": + version: 5.3.3 + resolution: "webpack-dev-middleware@npm:5.3.3" + dependencies: + colorette: ^2.0.10 + memfs: ^3.4.3 + mime-types: ^2.1.31 + range-parser: ^1.2.1 + schema-utils: ^4.0.0 + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + checksum: dd332cc6da61222c43d25e5a2155e23147b777ff32fdf1f1a0a8777020c072fbcef7756360ce2a13939c3f534c06b4992a4d659318c4a7fe2c0530b52a8a6621 + languageName: node + linkType: hard + +"webpack-dev-middleware@npm:^7.0.0": + version: 7.0.0 + resolution: "webpack-dev-middleware@npm:7.0.0" + dependencies: + colorette: ^2.0.10 + memfs: ^4.6.0 + mime-types: ^2.1.31 + range-parser: ^1.2.1 + schema-utils: ^4.0.0 + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + checksum: 90f6c87c80bd5849c34f3a1761ac7dc1b123def2e6e9922f55102ff4b7532538641fa8c7169ce8254b0d471c27d882cdf4a1c32979952474fc8eacc8b3447915 + languageName: node + linkType: hard + +"webpack-dev-server@npm:^4.15.1, webpack-dev-server@npm:^4.9.3": + version: 4.15.1 + resolution: "webpack-dev-server@npm:4.15.1" + dependencies: + "@types/bonjour": ^3.5.9 + "@types/connect-history-api-fallback": ^1.3.5 + "@types/express": ^4.17.13 + "@types/serve-index": ^1.9.1 + "@types/serve-static": ^1.13.10 + "@types/sockjs": ^0.3.33 + "@types/ws": ^8.5.5 + ansi-html-community: ^0.0.8 + bonjour-service: ^1.0.11 + chokidar: ^3.5.3 + colorette: ^2.0.10 + compression: ^1.7.4 + connect-history-api-fallback: ^2.0.0 + default-gateway: ^6.0.3 + express: ^4.17.3 + graceful-fs: ^4.2.6 + html-entities: ^2.3.2 + http-proxy-middleware: ^2.0.3 + ipaddr.js: ^2.0.1 + launch-editor: ^2.6.0 + open: ^8.0.9 + p-retry: ^4.5.0 + rimraf: ^3.0.2 + schema-utils: ^4.0.0 + selfsigned: ^2.1.1 + serve-index: ^1.9.1 + sockjs: ^0.3.24 + spdy: ^4.0.2 + webpack-dev-middleware: ^5.3.1 + ws: ^8.13.0 + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + bin: + webpack-dev-server: bin/webpack-dev-server.js + checksum: cd0063b068d2b938fd76c412d555374186ac2fa84bbae098265212ed50a5c15d6f03aa12a5a310c544a242943eb58c0bfde4c296d5c36765c182f53799e1bc71 + languageName: node + linkType: hard + +"webpack-dev-server@npm:^5.0.0": + version: 5.0.0 + resolution: "webpack-dev-server@npm:5.0.0" + dependencies: + "@types/bonjour": ^3.5.13 + "@types/connect-history-api-fallback": ^1.5.4 + "@types/express": ^4.17.21 + "@types/serve-index": ^1.9.4 + "@types/serve-static": ^1.15.5 + "@types/sockjs": ^0.3.36 + "@types/ws": ^8.5.10 + ansi-html-community: ^0.0.8 + bonjour-service: ^1.2.1 + chokidar: ^3.6.0 + colorette: ^2.0.10 + compression: ^1.7.4 + connect-history-api-fallback: ^2.0.0 + default-gateway: ^6.0.3 + express: ^4.17.3 + graceful-fs: ^4.2.6 + html-entities: ^2.4.0 + http-proxy-middleware: ^2.0.3 + ipaddr.js: ^2.1.0 + launch-editor: ^2.6.1 + open: ^10.0.3 + p-retry: ^6.2.0 + rimraf: ^5.0.5 + schema-utils: ^4.2.0 + selfsigned: ^2.4.1 + serve-index: ^1.9.1 + sockjs: ^0.3.24 + spdy: ^4.0.2 + webpack-dev-middleware: ^7.0.0 + ws: ^8.16.0 + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + bin: + webpack-dev-server: bin/webpack-dev-server.js + checksum: 419d1af6b6164900fb01168c3ef965fe8d27a78939ef8f5c602f82af5be8a2b68a0b015df564623dd69996d5265c679202c5970b59797e83cf322e47bbcd6022 + languageName: node + linkType: hard + +"webpack-merge@npm:^5.7.3, webpack-merge@npm:^5.8.0, webpack-merge@npm:^5.9.0": + version: 5.10.0 + resolution: "webpack-merge@npm:5.10.0" + dependencies: + clone-deep: ^4.0.1 + flat: ^5.0.2 + wildcard: ^2.0.0 + checksum: 1fe8bf5309add7298e1ac72fb3f2090e1dfa80c48c7e79fa48aa60b5961332c7d0d61efa8851acb805e6b91a4584537a347bc106e05e9aec87fa4f7088c62f2f + languageName: node + linkType: hard + +"webpack-sources@npm:^3.2.2, webpack-sources@npm:^3.2.3": + version: 3.2.3 + resolution: "webpack-sources@npm:3.2.3" + checksum: 989e401b9fe3536529e2a99dac8c1bdc50e3a0a2c8669cbafad31271eadd994bc9405f88a3039cd2e29db5e6d9d0926ceb7a1a4e7409ece021fe79c37d9c4607 + languageName: node + linkType: hard + +"webpack@npm:^5.73.0, webpack@npm:^5.88.1": + version: 5.89.0 + resolution: "webpack@npm:5.89.0" + dependencies: + "@types/eslint-scope": ^3.7.3 + "@types/estree": ^1.0.0 + "@webassemblyjs/ast": ^1.11.5 + "@webassemblyjs/wasm-edit": ^1.11.5 + "@webassemblyjs/wasm-parser": ^1.11.5 + acorn: ^8.7.1 + acorn-import-assertions: ^1.9.0 + browserslist: ^4.14.5 + chrome-trace-event: ^1.0.2 + enhanced-resolve: ^5.15.0 + es-module-lexer: ^1.2.1 + eslint-scope: 5.1.1 + events: ^3.2.0 + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.2.9 + json-parse-even-better-errors: ^2.3.1 + loader-runner: ^4.2.0 + mime-types: ^2.1.27 + neo-async: ^2.6.2 + schema-utils: ^3.2.0 + tapable: ^2.1.1 + terser-webpack-plugin: ^5.3.7 + watchpack: ^2.4.0 + webpack-sources: ^3.2.3 + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: 43fe0dbc30e168a685ef5a86759d5016a705f6563b39a240aa00826a80637d4a3deeb8062e709d6a4b05c63e796278244c84b04174704dc4a37bedb0f565c5ed + languageName: node + linkType: hard + +"webpack@npm:^5.90.1": + version: 5.90.1 + resolution: "webpack@npm:5.90.1" + dependencies: + "@types/eslint-scope": ^3.7.3 + "@types/estree": ^1.0.5 + "@webassemblyjs/ast": ^1.11.5 + "@webassemblyjs/wasm-edit": ^1.11.5 + "@webassemblyjs/wasm-parser": ^1.11.5 + acorn: ^8.7.1 + acorn-import-assertions: ^1.9.0 + browserslist: ^4.21.10 + chrome-trace-event: ^1.0.2 + enhanced-resolve: ^5.15.0 + es-module-lexer: ^1.2.1 + eslint-scope: 5.1.1 + events: ^3.2.0 + glob-to-regexp: ^0.4.1 + graceful-fs: ^4.2.9 + json-parse-even-better-errors: ^2.3.1 + loader-runner: ^4.2.0 + mime-types: ^2.1.27 + neo-async: ^2.6.2 + schema-utils: ^3.2.0 + tapable: ^2.1.1 + terser-webpack-plugin: ^5.3.10 + watchpack: ^2.4.0 + webpack-sources: ^3.2.3 + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: a7be844d5720a0c6282fec012e6fa34b1137dff953c5d48bf2ef066a6c27c1dbc92a9b9effc05ee61c9fe269499266db9782073f2d82a589d3c5c966ffc56584 + languageName: node + linkType: hard + +"webpackbar@npm:^5.0.2": + version: 5.0.2 + resolution: "webpackbar@npm:5.0.2" + dependencies: + chalk: ^4.1.0 + consola: ^2.15.3 + pretty-time: ^1.1.0 + std-env: ^3.0.1 + peerDependencies: + webpack: 3 || 4 || 5 + checksum: 214a734b1d4d391eb8271ed1b11085f0efe6831e93f641229b292abfd6fea871422dce121612511c17ae8047522be6d65c1a2666cabb396c79549816a3612338 + languageName: node + linkType: hard + +"websocket-driver@npm:>=0.5.1, websocket-driver@npm:^0.7.4": + version: 0.7.4 + resolution: "websocket-driver@npm:0.7.4" + dependencies: + http-parser-js: ">=0.5.1" + safe-buffer: ">=5.1.0" + websocket-extensions: ">=0.1.1" + checksum: fffe5a33fe8eceafd21d2a065661d09e38b93877eae1de6ab5d7d2734c6ed243973beae10ae48c6613cfd675f200e5a058d1e3531bc9e6c5d4f1396ff1f0bfb9 + languageName: node + linkType: hard + +"websocket-extensions@npm:>=0.1.1": + version: 0.1.4 + resolution: "websocket-extensions@npm:0.1.4" + checksum: 5976835e68a86afcd64c7a9762ed85f2f27d48c488c707e67ba85e717b90fa066b98ab33c744d64255c9622d349eedecf728e65a5f921da71b58d0e9591b9038 + languageName: node + linkType: hard + +"whatwg-url@npm:^11.0.0": + version: 11.0.0 + resolution: "whatwg-url@npm:11.0.0" + dependencies: + tr46: ^3.0.0 + webidl-conversions: ^7.0.0 + checksum: ed4826aaa57e66bb3488a4b25c9cd476c46ba96052747388b5801f137dd740b73fde91ad207d96baf9f17fbcc80fc1a477ad65181b5eb5fa718d27c69501d7af + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: ~0.0.3 + webidl-conversions: ^3.0.0 + checksum: b8daed4ad3356cc4899048a15b2c143a9aed0dfae1f611ebd55073310c7b910f522ad75d727346ad64203d7e6c79ef25eafd465f4d12775ca44b90fa82ed9e2c + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.2": + version: 1.1.13 + resolution: "which-typed-array@npm:1.1.13" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.4 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-tostringtag: ^1.0.0 + checksum: 3828a0d5d72c800e369d447e54c7620742a4cc0c9baf1b5e8c17e9b6ff90d8d861a3a6dd4800f1953dbf80e5e5cec954a289e5b4a223e3bee4aeb1f8c5f33309 + languageName: node + linkType: hard + +"which@npm:^1.3.1": + version: 1.3.1 + resolution: "which@npm:1.3.1" + dependencies: + isexe: ^2.0.0 + bin: + which: ./bin/which + checksum: f2e185c6242244b8426c9df1510e86629192d93c1a986a7d2a591f2c24869e7ffd03d6dac07ca863b2e4c06f59a4cc9916c585b72ee9fa1aa609d0124df15e04 + languageName: node + linkType: hard + +"which@npm:^2.0.1, which@npm:^2.0.2": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: ^2.0.0 + bin: + node-which: ./bin/node-which + checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 + languageName: node + linkType: hard + +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: ^3.1.1 + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + languageName: node + linkType: hard + +"widest-line@npm:^3.1.0": + version: 3.1.0 + resolution: "widest-line@npm:3.1.0" + dependencies: + string-width: ^4.0.0 + checksum: 03db6c9d0af9329c37d74378ff1d91972b12553c7d72a6f4e8525fe61563fa7adb0b9d6e8d546b7e059688712ea874edd5ded475999abdeedf708de9849310e0 + languageName: node + linkType: hard + +"widest-line@npm:^4.0.1": + version: 4.0.1 + resolution: "widest-line@npm:4.0.1" + dependencies: + string-width: ^5.0.1 + checksum: 64c48cf27171221be5f86fc54b94dd29879165bdff1a7aa92dde723d9a8c99fb108312768a5d62c8c2b80b701fa27bbd36a1ddc58367585cd45c0db7920a0cba + languageName: node + linkType: hard + +"wildcard@npm:^2.0.0": + version: 2.0.1 + resolution: "wildcard@npm:2.0.1" + checksum: e0c60a12a219e4b12065d1199802d81c27b841ed6ad6d9d28240980c73ceec6f856771d575af367cbec2982d9ae7838759168b551776577f155044f5a5ba843c + languageName: node + linkType: hard + +"wordwrapjs@npm:^4.0.0": + version: 4.0.1 + resolution: "wordwrapjs@npm:4.0.1" + dependencies: + reduce-flatten: ^2.0.0 + typical: ^5.2.0 + checksum: 3d927f3c95d0ad990968da54c0ad8cde2801d8e91006cd7474c26e6b742cc8557250ce495c9732b2f9db1f903601cb74ec282e0f122ee0d02d7abe81e150eea8 + languageName: node + linkType: hard + +"wordwrapjs@npm:^5.1.0": + version: 5.1.0 + resolution: "wordwrapjs@npm:5.1.0" + checksum: 063c7a5a85b694be1a5fd96f7ae0c0f4d717a087909e5c70cf25edec6eb5df5f2f5561f23e939cf6d7514cf81902610f74f288ef1612a49bf5451de15e0e29db + languageName: node + linkType: hard + +"workerpool@npm:6.2.1": + version: 6.2.1 + resolution: "workerpool@npm:6.2.1" + checksum: c2c6eebbc5225f10f758d599a5c016fa04798bcc44e4c1dffb34050cd361d7be2e97891aa44419e7afe647b1f767b1dc0b85a5e046c409d890163f655028b09d + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b + languageName: node + linkType: hard + +"wrap-ansi@npm:^6.2.0": + version: 6.2.0 + resolution: "wrap-ansi@npm:6.2.0" + dependencies: + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: 6cd96a410161ff617b63581a08376f0cb9162375adeb7956e10c8cd397821f7eb2a6de24eb22a0b28401300bf228c86e50617cd568209b5f6775b93c97d2fe3a + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.0.1, wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: ^6.1.0 + string-width: ^5.0.1 + strip-ansi: ^7.0.1 + checksum: 371733296dc2d616900ce15a0049dca0ef67597d6394c57347ba334393599e800bab03c41d4d45221b6bc967b8c453ec3ae4749eff3894202d16800fdfe0e238 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 + languageName: node + linkType: hard + +"write-file-atomic@npm:^3.0.0, write-file-atomic@npm:^3.0.3": + version: 3.0.3 + resolution: "write-file-atomic@npm:3.0.3" + dependencies: + imurmurhash: ^0.1.4 + is-typedarray: ^1.0.0 + signal-exit: ^3.0.2 + typedarray-to-buffer: ^3.1.5 + checksum: c55b24617cc61c3a4379f425fc62a386cc51916a9b9d993f39734d005a09d5a4bb748bc251f1304e7abd71d0a26d339996c275955f527a131b1dcded67878280 + languageName: node + linkType: hard + +"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" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: feb3eecd2bae82fa8a8beef800290ce437d8b8063bdc69712725f21aef77c49cb2ff45c6e5e7fce622248f9c7abaee506bae0a9064067ffd6935460c7357321b + languageName: node + linkType: hard + +"ws@npm:8.5.0": + version: 8.5.0 + resolution: "ws@npm:8.5.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 76f2f90e40344bf18fd544194e7067812fb1372b2a37865678d8f12afe4b478ff2ebc0c7c0aff82cd5e6b66fc43d889eec0f1865c2365d8f7a66d92da7744a77 + languageName: node + linkType: hard + +"ws@npm:^7.3.1, ws@npm:^7.4.2, ws@npm:^7.4.6": + version: 7.5.9 + resolution: "ws@npm:7.5.9" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: c3c100a181b731f40b7f2fddf004aa023f79d64f489706a28bc23ff88e87f6a64b3c6651fbec3a84a53960b75159574d7a7385709847a62ddb7ad6af76f49138 + languageName: node + linkType: hard + +"ws@npm:^8.13.0": + version: 8.15.0 + resolution: "ws@npm:8.15.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: ca15c590aa49bc0197223b8ab7d15e7362ae6c4011d91ed0e5cd5867cdd5497fd71470ea36314833b4b078929fe64dc4ba7748b1e58e50a0f8e41f147db2b464 + languageName: node + linkType: hard + +"xdg-basedir@npm:^4.0.0": + version: 4.0.0 + resolution: "xdg-basedir@npm:4.0.0" + checksum: 0073d5b59a37224ed3a5ac0dd2ec1d36f09c49f0afd769008a6e9cd3cd666bd6317bd1c7ce2eab47e1de285a286bad11a9b038196413cd753b79770361855f3c + languageName: node + linkType: hard + +"xdg-basedir@npm:^5.0.1, xdg-basedir@npm:^5.1.0": + version: 5.1.0 + resolution: "xdg-basedir@npm:5.1.0" + checksum: b60e8a2c663ccb1dac77c2d913f3b96de48dafbfa083657171d3d50e10820b8a04bb4edfe9f00808c8c20e5f5355e1927bea9029f03136e29265cb98291e1fea + languageName: node + linkType: hard + +"xml-js@npm:^1.6.11": + version: 1.6.11 + resolution: "xml-js@npm:1.6.11" + dependencies: + sax: ^1.2.4 + bin: + xml-js: ./bin/cli.js + checksum: 24a55479919413687105fc2d8ab05e613ebedb1c1bc12258a108e07cff5ef793779297db854800a4edf0281303ebd1f177bc4a588442f5344e62b3dddda26c2b + languageName: node + linkType: hard + +"xtend@npm:^2.2.0": + version: 2.2.0 + resolution: "xtend@npm:2.2.0" + checksum: 9fcd1ddabefdb3c68a698b08177525ad14a6df3423b13bad9a53900d19374e476a43c219b0756d39675776b2326a35fe477c547cfb8a05ae9fea4ba2235bebe2 + languageName: node + linkType: hard + +"xtend@npm:^4.0.0, xtend@npm:^4.0.1": + version: 4.0.2 + resolution: "xtend@npm:4.0.2" + checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a + languageName: node + linkType: hard + +"xtend@npm:~2.0.4": + version: 2.0.6 + resolution: "xtend@npm:2.0.6" + dependencies: + is-object: ~0.1.2 + object-keys: ~0.2.0 + checksum: 414531e51cbc56d4676ae2b3a4070052e0c7a36caf7ee74f2e8449fe0fc1752b971a776fca5b85ec02ef3d0a33b8e75491d900474b8407f3f4bba3f49325a785 + languageName: node + linkType: hard + +"xtend@npm:~2.1.2": + version: 2.1.2 + resolution: "xtend@npm:2.1.2" + dependencies: + object-keys: ~0.4.0 + checksum: a8b79f31502c163205984eaa2b196051cd2fab0882b49758e30f2f9018255bc6c462e32a090bf3385d1bda04755ad8cc0052a09e049b0038f49eb9b950d9c447 + languageName: node + linkType: hard + +"xtend@npm:~3.0.0": + version: 3.0.0 + resolution: "xtend@npm:3.0.0" + checksum: ecdc4dd74f26e561dbc13d4148fcc7b8f46f49b9259862fc31e42b7cede9eee62af9d869050a7b8e089475e858744a74ceae3f0da2943755ef712f3277ad2e50 + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 54f0fb95621ee60898a38c572c515659e51cc9d9f787fb109cef6fde4befbe1c4602dc999d30110feee37456ad0f1660fa2edcfde6a9a740f86a290999550d30 + languageName: node + linkType: hard + +"yallist@npm:^3.0.2": + version: 3.1.1 + resolution: "yallist@npm:3.1.1" + checksum: 48f7bb00dc19fc635a13a39fe547f527b10c9290e7b3e836b9a8f1ca04d4d342e85714416b3c2ab74949c9c66f9cebb0473e6bc353b79035356103b47641285d + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 + languageName: node + linkType: hard + +"yaml@npm:^1.10.0, yaml@npm:^1.10.2, yaml@npm:^1.7.2": + version: 1.10.2 + resolution: "yaml@npm:1.10.2" + checksum: ce4ada136e8a78a0b08dc10b4b900936912d15de59905b2bf415b4d33c63df1d555d23acb2a41b23cf9fb5da41c256441afca3d6509de7247daa062fd2c5ea5f + languageName: node + linkType: hard + +"yaml@npm:^2.2.2, yaml@npm:^2.3.4": + version: 2.3.4 + resolution: "yaml@npm:2.3.4" + checksum: e6d1dae1c6383bcc8ba11796eef3b8c02d5082911c6723efeeb5ba50fc8e881df18d645e64de68e421b577296000bea9c75d6d9097c2f6699da3ae0406c030d8 + languageName: node + linkType: hard + +"yargs-parser@npm:20.2.4": + version: 20.2.4 + resolution: "yargs-parser@npm:20.2.4" + checksum: d251998a374b2743a20271c2fd752b9fbef24eb881d53a3b99a7caa5e8227fcafd9abf1f345ac5de46435821be25ec12189a11030c12ee6481fef6863ed8b924 + languageName: node + linkType: hard + +"yargs-parser@npm:^20.2.2": + version: 20.2.9 + resolution: "yargs-parser@npm:20.2.9" + checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 + languageName: node + linkType: hard + +"yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: ed2d96a616a9e3e1cc7d204c62ecc61f7aaab633dcbfab2c6df50f7f87b393993fe6640d017759fe112d0cb1e0119f2b4150a87305cc873fd90831c6a58ccf1c + languageName: node + linkType: hard + +"yargs-unparser@npm:2.0.0": + version: 2.0.0 + resolution: "yargs-unparser@npm:2.0.0" + dependencies: + camelcase: ^6.0.0 + decamelize: ^4.0.0 + flat: ^5.0.2 + is-plain-obj: ^2.1.0 + checksum: 68f9a542c6927c3768c2f16c28f71b19008710abd6b8f8efbac6dcce26bbb68ab6503bed1d5994bdbc2df9a5c87c161110c1dfe04c6a3fe5c6ad1b0e15d9a8a3 + languageName: node + linkType: hard + +"yargs@npm:16.2.0": + version: 16.2.0 + resolution: "yargs@npm:16.2.0" + dependencies: + cliui: ^7.0.2 + escalade: ^3.1.1 + get-caller-file: ^2.0.5 + require-directory: ^2.1.1 + string-width: ^4.2.0 + y18n: ^5.0.5 + yargs-parser: ^20.2.2 + checksum: b14afbb51e3251a204d81937c86a7e9d4bdbf9a2bcee38226c900d00f522969ab675703bee2a6f99f8e20103f608382936034e64d921b74df82b63c07c5e8f59 + languageName: node + linkType: hard + +"yargs@npm:17.7.2, yargs@npm:^17.7.1": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + 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: 73b572e863aa4a8cbef323dd911d79d193b772defd5a51aab0aca2d446655216f5002c42c5306033968193bdbf892a7a4c110b0d77954a7fdf563e653967b56a + languageName: node + linkType: hard + +"yauzl@npm:^2.10.0": + version: 2.10.0 + resolution: "yauzl@npm:2.10.0" + dependencies: + buffer-crc32: ~0.2.3 + fd-slicer: ~1.1.0 + checksum: 7f21fe0bbad6e2cb130044a5d1d0d5a0e5bf3d8d4f8c4e6ee12163ce798fee3de7388d22a7a0907f563ac5f9d40f8699a223d3d5c1718da90b0156da6904022b + languageName: node + linkType: hard + +"ylru@npm:^1.2.0": + version: 1.3.2 + resolution: "ylru@npm:1.3.2" + checksum: b6bb3931144424114f2350c072cfeb180f205add93509c605ae025cbed8059846f8a5767655feeeab890d288b5b4c4b36f5d5d867ee4e6946c16bcc7ec3ddaee + languageName: node + linkType: hard + +"yn@npm:3.1.1": + version: 3.1.1 + resolution: "yn@npm:3.1.1" + checksum: 2c487b0e149e746ef48cda9f8bad10fc83693cd69d7f9dcd8be4214e985de33a29c9e24f3c0d6bcf2288427040a8947406ab27f7af67ee9456e6b84854f02dd6 + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 + languageName: node + linkType: hard + +"yocto-queue@npm:^1.0.0": + version: 1.0.0 + resolution: "yocto-queue@npm:1.0.0" + checksum: 2cac84540f65c64ccc1683c267edce396b26b1e931aa429660aefac8fbe0188167b7aee815a3c22fa59a28a58d898d1a2b1825048f834d8d629f4c2a5d443801 + languageName: node + linkType: hard + +"zwitch@npm:^1.0.0": + version: 1.0.5 + resolution: "zwitch@npm:1.0.5" + checksum: 28a1bebacab3bc60150b6b0a2ba1db2ad033f068e81f05e4892ec0ea13ae63f5d140a1d692062ac0657840c8da076f35b94433b5f1c329d7803b247de80f064a + languageName: node + linkType: hard + +"zwitch@npm:^2.0.0": + version: 2.0.4 + resolution: "zwitch@npm:2.0.4" + checksum: f22ec5fc2d5f02c423c93d35cdfa83573a3a3bd98c66b927c368ea4d0e7252a500df2a90a6b45522be536a96a73404393c958e945fdba95e6832c200791702b6 + languageName: node + linkType: hard